www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Array init

reply bearophile <bearophileHUGS lycos.com> writes:
A question about D1 specs (that may be useful for LDC).

In the following code there's anarray of structs S. Is it OK, according to D1
specs, to not initialize the memory of this array if the compiler sees that all
fields of S have a void init?

struct S { double x = void, y = void; }
void main() {
  auto a = new S[1000];
}

Bye,
bearophile
Aug 31 2009
parent reply Max Samukha <spambox d-coding.com> writes:
bearophile wrote:

 A question about D1 specs (that may be useful for LDC).
 
 In the following code there's anarray of structs S. Is it OK, according to
 D1 specs, to not initialize the memory of this array if the compiler sees
 that all fields of S have a void init?
 
 struct S { double x = void, y = void; }
 void main() {
   auto a = new S[1000];
 }
 
 Bye,
 bearophile
That's an interesting question. The compiler does set void-initialized member variables to zeros: struct S { double x = void, y = void; } void main() { S s; // x and y are initialized to 0 } I think this is a bug. Such members should be left uninitialized or initialized to the default initializer for the type (NaN in this case) or void initialization should be disallowed for member variables.
Sep 01 2009
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 01 Sep 2009 07:06:25 -0400, Max Samukha <spambox d-coding.com>  
wrote:

 bearophile wrote:

 A question about D1 specs (that may be useful for LDC).

 In the following code there's anarray of structs S. Is it OK, according  
 to
 D1 specs, to not initialize the memory of this array if the compiler  
 sees
 that all fields of S have a void init?

 struct S { double x = void, y = void; }
 void main() {
   auto a = new S[1000];
 }

 Bye,
 bearophile
That's an interesting question. The compiler does set void-initialized member variables to zeros: struct S { double x = void, y = void; } void main() { S s; // x and y are initialized to 0 } I think this is a bug. Such members should be left uninitialized or initialized to the default initializer for the type (NaN in this case) or void initialization should be disallowed for member variables.
An initialized double is NaN, so I don't think the compiler is initializing those variables. Your test is not valid, you need to fill the memory with something to see if the code doesn't change it. Try this: foo() { S s; // display s's members here s.x = s.y = 555; } void main() { foo(); foo(); } This will make the compiler reuse the stack memory, which should be initialized to 555 on the second run. But I think in answer to bearophile's question, you probably need to perform a similar test for allocation, getting the GC to allocate the same memory twice. Even so, the GC propbably zeros out all memory before returning it, to cut down on false pointers being detected by the GC on a collection cycle. I'm not knowledgable with the details of the GC, so I could be completely wrong. At the very least, the compiler needs to initialize the memory in the block that was returned but not requested, to avoid false pointers. -Steve
Sep 01 2009
parent reply Max Samukha <spambox d-coding.com> writes:
Steven Schveighoffer wrote:

 That's an interesting question. The compiler does set void-initialized
 member variables to zeros:

 struct S { double x = void, y = void; }
 void main() {
     S s; // x and y are initialized to 0
 }

 I think this is a bug. Such members should be left uninitialized or
 initialized to the default initializer for the type (NaN in this case) or
 void initialization should be disallowed for member variables.
An initialized double is NaN, so I don't think the compiler is initializing those variables. Your test is not valid, you need to fill the memory with something to see if the code doesn't change it.
I should have posted the asm listing of the test case. The compiler does generate initialization code that sets the memory allocated for the structure to zeros, which defeats the purpose of void initializers. ... dd offset FLAT:_D4Test1S6__initZ SYM32 db 000h,000h,000h,000h,000h,000h,000h,000h db 000h,000h,000h,000h,000h,000h,000h,000h ... _Dmain: push EBP mov EBP,ESP sub ESP,010h push ESI push EDI mov ESI,offset FLAT:_D4Test1S6__initZ SYM32 lea EDI,-010h[EBP] movsd movsd movsd movsd xor EAX,EAX pop EDI pop ESI leave ret .text._Dmain ends I guess the rationale behind this behavior is that filling void-initialized fields with zeros may be as fast or faster than skipping them while selectively initializing other fields. IMO, the initialization code shouldn't be generated for aggregates that have all members void-initialized, and consequently for arrays of such aggregates.
Sep 01 2009
next sibling parent reply Don <nospam nospam.com> writes:
Max Samukha wrote:
 Steven Schveighoffer wrote:
 
 That's an interesting question. The compiler does set void-initialized
 member variables to zeros:

 struct S { double x = void, y = void; }
 void main() {
     S s; // x and y are initialized to 0
 }

 I think this is a bug. Such members should be left uninitialized or
 initialized to the default initializer for the type (NaN in this case) or
 void initialization should be disallowed for member variables.
An initialized double is NaN, so I don't think the compiler is initializing those variables. Your test is not valid, you need to fill the memory with something to see if the code doesn't change it.
I should have posted the asm listing of the test case. The compiler does generate initialization code that sets the memory allocated for the structure to zeros, which defeats the purpose of void initializers. ... dd offset FLAT:_D4Test1S6__initZ SYM32 db 000h,000h,000h,000h,000h,000h,000h,000h db 000h,000h,000h,000h,000h,000h,000h,000h ... _Dmain: push EBP mov EBP,ESP sub ESP,010h push ESI push EDI mov ESI,offset FLAT:_D4Test1S6__initZ SYM32 lea EDI,-010h[EBP] movsd movsd movsd movsd xor EAX,EAX pop EDI pop ESI leave ret .text._Dmain ends I guess the rationale behind this behavior is that filling void-initialized fields with zeros may be as fast or faster than skipping them while selectively initializing other fields.
Yes, it would definitely be faster if everything else is initialized to zero.
 IMO, the initialization code shouldn't be generated for aggregates that have 
 all members void-initialized, and consequently for arrays of such 
 aggregates.
Agreed. (But it's just a performance issue, it's not incorrect to initialize them to zero).
Sep 01 2009
parent Max Samukha <spambox d-coding.com> writes:
Don wrote:

 
 Agreed. (But it's just a performance issue, it's not incorrect to
 initialize them to zero).
And void initializers are all about performance :) Otherwise, they are useless.
Sep 01 2009
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Max Samukha:
 IMO, the initialization code shouldn't be generated for aggregates that have 
 all members void-initialized, and consequently for arrays of such 
 aggregates.
Thanks to all people that have given me answers and opinions. I have discussed this topic a bit with Tomas Lindquist Olsen, LDC may be improved a bit. Regarding test code for present and future D1 compilers I written this: version (Tango) import tango.stdc.stdlib: atof; else import std.c.stdlib: atof; version (V1) void main() { struct S { double x, y; } S s; s.x = atof("10.0"); s.y = atof("20.0"); } version (V2) void main() { struct S { double x, y; } S s = void; s.x = atof("10.0"); s.y = atof("20.0"); } version (V3) void main() { struct S { double x, y; } auto s = S(atof("10.0"), atof("20.0")); } version (V4) void main() { struct S { double x = void, y = void; } S s; s.x = atof("10.0"); s.y = atof("20.0"); } version (V5) void main() { struct S { double x = void, y = void; } S s = void; s.x = atof("10.0"); s.y = atof("20.0"); } version (V6) void main() { struct S { double x = void, y = void; } auto s = S(atof("10.0"), atof("20.0")); } I think that in theory a good D compiler has to produce the same optimal code in all those six cases (in some cases removing some double initializations too) :-) I'll show this code to Lindquist in future. Bye, bearophile
Sep 01 2009