"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP************************@msnews.microsoft.c om...
Mark R. Dawson <Ma*********@discussions.microsoft.comwrote:
>Hi Jon,
in the article there is the comment:
"Every static variable is stored on the heap, regardless of whether it's
declared within a reference type or a value type. There is only one slot in
total no matter how many instances are created. (There don't need to be any
instances created for that one slot to exist though.) Note that this heap is
separate from the normal garbage collected heap - it's known as a "high
frequency heap", and there's one per application domain. "
However, from reading this article:
http://msdn.microsoft.com/msdnmag/is...5/JITCompiler/
It makes the comment that only primitive static types will be stored on the
high frequency heap, whereas static value types and reference types are still
stored on the normal GC Heap.
Ooh, interesting. I'll look into it - thanks very much. The stuff about
the high frequency heap was going on what Willy has said in the past :)
I suspect that it's better for the sake of simplicity to remove the
reference to the high frequency heap and just refer to that article...
--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jon, the article is wrong.
static fields whatever their type are always stored on the HighFrequencyHeap, they can never
be members of object instances , so they are NEVER on the GC heap.
Consider following sample and my anotations.
....
class C
{
public int sc = 0;
public static S s;
}
public struct S
{
public int w;
public static long l;
}
class Program
{
static int v = 123;
static void Main()
{
S s1 = new S(); [1]
v = 128; [2]
C c1 = new C(); [3]
C.s = new S(); [4]
C c2 = new C(); [5]
S.l = 0xffffffffff; [6]
C.s.w = 255; [7]
s1.w = 123; [8]
}
}
[1] allocates s1 on the stack. But finally what get's on the stack is only the contents of
S.w, S.l ends on the (HighFrequencyHeap) HFH, and stays there until the AD unloads, s1 stays
on the stack until the stack unwinds.
[2] That's an easy one, v is on the HFH, and is assigned the value 128.
[3] c1 is a reference to a type C on the GC heap. It's 's' variable however, gets stored on
the HFH, and stay's there until the AD unloads. Note, it's size is 12 bytes only, that is
the header+sizeof(int), assuming X86 here. the instance gets freed when GC'd.
[4] Now it gets really complicated, the variable C.s is static, so, it's on the HFH, the
value pointed to by C.s gets stored on the GC heap, but there you'll find only the field
S.w, the static field S.l gets stored on the HFH.
[5] Here I create a new instance of C. Here c2 points to an instance of C on the GC heap.
But, it's "s" field is on the HFH, actually it's the same field as c1.S (that is same
address, so same value).
[6] assign a large value to S.l (on the HFH see 1).
[7] C.s.w is assigned a value 255, this value is on the GC heap see [4]
[8] s1.w is assigned the value 123, this value ends on the stack (see 1)
You can inspect this all, by using a native debugger like Windbg.exe, take care however when
using the SOS .DLL extension, this one gives you the wrong impression that static's are
instance members and stored in-line on the GC heap, but if you watch carefully you'll see
that effectively the static's are stored elsewhere (this is quite obvious isn't it, how
could they otherwise survive a GC sweep?).
To illustrate this last point, consider the debugger SOS output...
0:000!do 029b19cc
Name: Willys.C
MethodTable: 00103198
EEClass: 00101844
Size: 12(0xc) bytes
(C:\Develop\netfx\Junk\objlayout.exe)
Fields:
MT Field Offset Type VT Attr Value Name
790ff7f0 4000001 4 System.Int32 0 instance 0 sc
00103124 4000002 4 Willys.S 1 static 029b19a4 s
0:000dd 029b19cc
029b19cc 00103198 00000000 00000000 00103198
!do dumps the object at address 029b19cc (the GC heap), the output makes you believe that
the static field is part of the instance, well it's NOT and I think the author of the
article in MSDN Mag made the mistake in believing it was.
Note the size (12 bytes), that includes the sync#, MT pointer and an instance field 'sc'.
Note also the next field, see it's offset.... and it's attribute (static) so you see it's
not part of the instance...
notice also the fields value (029b19a4 ) again this is a pointer to the GC heap..
the "dd" command dumps the real contents of the address (029b19cc ), which is the real
object contents (less the sync# field), the first DWORD (00103198 ) is the MT pointer and
the next DWORD (00000000) is the value of sc, and that's it.
Willy.