cody said:
unlikely.
No. Locals and structs are created on the stack which does *not* contain
zeros, but instead data of previous method invocations.
If a method returns it would have to overwrite the stack with zeros to
clean
up, if you want the behavour that every struct is generated in "null
memory".
That is partially incorrect, as was my original statement.
[quote from CIL Partition 1, page 87 of the MSWord version]
A local variable may hold any data type. However, a particular slot shall
be used in a type consistent way (where the type system is the one described
in clause 11.3.2.1). Local variables are initialized to 0 before entry if
the initialize flag for the method is set (see Section 11.2). The address
of an individual local variable may be taken using the ldloca instruction.
[end quote]
Note "Local variables are initialized to 0 before entry if the initalize
flag for the method is set". This shows that variables are initalized to 0
in almost every case(I've *NEVER* seen IL without that flag), and in this
case the C# compiler generates superflous code with the initobj instruction.
So, indeed, there is generally no reason to do this(and, actually, reference
variables will always be null at calltime, both in and outside of valuetypes
on the stack). Other tests have shown that booleans are set to false as
well(I've yet to manage to make it have a different value). I do wonder
about performance here...it seems to me that it would be as or perhaps more
efficient to zero the small local block(which is almost always small) than
it would be to analyze the local block and zero out only select fields. That
does seem odd to me.
Also, this same document virtualizes the stack as a singly linked list,
meaning that there is no apparent explicit requirement for saving stack
frames in any given place or for using a traditional growing stack. While I
do think the current implementation does use that for ease of implementation
reasons, it isn't definite and assuming that a new stack frame would exist
where an old one did will probably be incorrect at some point.
C# forces you to initialize *every* local variable completely before first
use. In the case of structs a ctor call is not needed if you assign all
fields manually.
Yes, but I don't think it has much to do with the underlying system as much
as clean coding. Forcing explicit definition forces you to know what is
assigned(and makes life easier since you don't have to worry about the
differing defaults that can come up). The CLR doesn't require it, its
strictly a convention forced by C#(which also sets the init flag, causing
double zeroing). Also, while this looks like a constructor call, it isn't,
its C# sugar(at least in most cases, I havn't tested valuetypes with default
constructors. C++ should allow this, but it may or may not be consumable by
C#). For a value type, a call instruction is issued to call the constructor,
vs a newobj instruction which is used for a reference type. The entire
purpose of initobj is to initalize to zero\null\0.0\false(although for
pimatives like bool, the C# compiler emits ldc.i4.0 instead of initobj).
Think: Would the initobj call would make sense in any circumstance when
structs would already zeroed out a creation time?
No, but its there, one would hope the JIT would ignore it. This is an
artifiact of the compiler. I would assume the C# compiler flow control
doesn't interlink with the codegen, the compiler doesn't explicitly need to
emit initobj because it sets the local init flag, however instead of
attempting an optimization of tracking variable usage and deciding when to
issue the initobj instruction, the compiler prefers to do a literal(and
simplier) translation of your code and emits the initobj instruction.
However, due to some strange inconsistencies in the runtime, there is a
chance that initobj is needed in the case you are using strange valuetypes.
Which situation? I'd like to hear.
There isn't one, per se. It is either 1) a bug in this complier or 2) the
convention is being dropped. Sometime in the near future I'll make an
inquiry about that, but its irrelevent right now.
Now, if you have proof(empirical, anecdotal, or documented) of an error
here, I am quite interested. The docs aren't particularly clear and my
reading may or may not be correct. I am not interested in C++ or x86's
memory or call models however.