January 17, 2007 Default initializers (or: win32 bindings' struct sizes) | ||||
---|---|---|---|---|
| ||||
Hi, Many structures in the win32 bindings project on dsource set their size using D's default initializer: #struct STARTUPINFOA { # DWORD cb = STARTUPINFOA.sizeof; # LPSTR lpReserved; #//... #} 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. |
January 17, 2007 Re: Default initializers (or: win32 bindings' struct sizes) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lionello Lunesu | 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. |
Copyright © 1999-2021 by the D Language Foundation