digitalmars.D - Default initializers (or: win32 bindings' struct sizes)
- Lionello Lunesu (30/30) Jan 17 2007 Hi,
- Frits van Bommel (43/53) Jan 17 2007 Actually, it's not (only) about custom initializers:
Hi, Many structures in the win32 bindings project on dsource set their size using D's default initializer: #struct STARTUPINFOA { This does save some typing when in Win32 projects, but results in unexpected linker errors (dmd 1.0): Error 42: Symbol Undefined _D5win327winbase12STARTUPINFOA6__initZ These errors can only be solved by 1) adding the appropriate .d files from the win32 folder on the command line, or 2) building a win32.lib (containing all initializers) and linking to it; 3) commenting out the "= ...sizeof;" part. All of which seem inappropriate for a bindings project that merely contains translated headers. One solution might be to add a version(..) around all default initializer, providing both an initialized and uninitialized version. Another, far better, solution would be to change DMD: the compiler knows the initializer and can safely inline it. What's more, the there are no linker errors for the default built-in initializers: struct S { int s; } // no linker error struct D { int d=0; } // linker error! The linking error occurs even with the -O -release -inline flags. Why does DMD (I don't know about GDC) require that __init symbol for custom initializers and not for the default ones? Is there any chance that this requirement will be dropped? L.
Jan 17 2007
Lionello Lunesu wrote:What's more, the there are no linker errors for the default built-in initializers: struct S { int s; } // no linker error struct D { int d=0; } // linker error! The linking error occurs even with the -O -release -inline flags. Why does DMD (I don't know about GDC) require that __init symbol for custom initializers and not for the default ones? Is there any chance that this requirement will be dropped?Actually, it's not (only) about custom initializers: ***** urxae urxae:~/tmp$ cat test.d import test2; import std.stdio; void main() { S s; writefln(cast(int)s.c); } urxae urxae:~/tmp$ cat test2.d struct S { char c; } urxae urxae:~/tmp$ dmd test.d gcc test.o -o test -m32 -lphobos -lpthread -lm -Xlinker -L/home/urxae/opt/dmd/lib test.o: In function `_Dmain': test.d:(.gnu.linkonce.t_Dmain+0x7): undefined reference to `_D5test21S6__initZ' collect2: ld returned 1 exit status --- errorlevel 1 ***** (Similarly fails for wchar, dchar, float, double and real) It looks to be about everything but *all-zero* default initializers. Those seem to be the only ones not to need explicit initializers to be generated if the type is used as a local variable. Their initialization is inlined. For some reason the inlining doesn't happen for explicitly zero-initialized variables, nor for non-zero or non-default initializers. This despite the fact that global/static variables seem to get the initializer "inlined" into the '.data' or (if all-zero) '.bss' section[1]. So it's not that the compiler doesn't know what the initializers should be, it's that the code generated to initialize local variables at run-time depends on the initializer data being generated by compilation of the imported module if it's either non-default or not all-zero. Preventing your link error would be a simple matter of treating initializer symbols similar to templates: put them in link-once sections in every object file where they're needed. Not that I'm saying this should necessarily be done; I'm just saying it should be relatively simple to implement. [1]: At least, those are the names on Linux (and anywhere else that uses ELF binaries, for that matter). Not sure what they are on Windows, but the principle should be similar.
Jan 17 2007