[BUG] ld behavior varies for C++ static initializer depending on .a or .o input

Hal Black black@ieee.org
Sat Apr 12 18:01:00 GMT 2003


Thanks for replying, Ian.

Ian Lance Taylor wrote:

> Hal Black <black@ieee.org> writes:
> 
> 
>>What I'm saying is not to use all the symbols, but to include all
>>static initializers as "symbols that are being looked for".  Even if
>>they aren't explicitly referenced by annother piece of code, they are
>>implicitly referenced by virtue of being static initializers.
> 
> 
> That would mean that every static initializer in a .a file would be
> brought in

Yes, as desired.

 > which would doubtless bring in other object files as well.

If the static initializer calls other functions, then those would be 
required as well, just as normal ld behavior.

> It means that including any class with a static initializer in a .a
> file would mean that that class would be included in all programs
> linked with that .a file.

Yes.  That's the desired behavior.  If a developer were to develop a 
library with a static initializer with side-effects, it would be 
something that should be called whenever that library was used.

Other classes with no static initializers would only be used as needed, 
as they are now.

If you don't think this is the proper usage, what is your interpretation 
of the meaning of having a static intializer (or items with static 
storage duration in general) in a library?

 >  This would go against the very idea of a .a
> file, which is that only required objects are included.

My claim is that if it has a static initializer, it is required.  If it 
is called from any included object, it is required (as it works now). 
Therefore this doesn't break the idea the only required objects are 
included.

-----
Also, just to clarify since it got lost in the quoting, I'm talking 
about this scenario:

class A {
public:
     A() { printf("Hello world!\n"); }
};
A a;

I claim if this code is put in a library, printf should be called. 
Because "a" has static storage duration and has side effects, its 
initializer cannot be eliminated per 3.7.1.2 of the draft standard.

So, when I say static initializer in the context of this discussion, the 
above code fragment is what I mean.

>>I would say that not looking for static initializers constitutes
>>eliminating them...
> 
> No, because they were never included in the first place.

The claim is that never including them in the first place is elimination.

> It's reasonably easy to avoid this problem: put the static initializer
> in the same source file as a class virtual function.  Since the
> class virtual function must be included, the initializer will be
> brought in as well.

The claim is that static initializers as specified above are in this 
same category of things that must be included.

> If you don't have any virtual functions, then you do need to take some
> other action to force that object file to be included, such as using
> global variables in some way.
> 
> Or maybe .a files are simply the wrong tool for the job.  Maybe you
> should use ld -r to form several .o files into one large .o file.
> Linking against that will ensure that everything is brought in.

Thanks for large .o idea.  This, and other workarounds such as the one 
provided by Alexandre, would work great for my immediate purposes.

However, I'm not having a problem finding a workaround, I'm addressing 
the point of how static initializers should behave in a library.  The 
workarounds proposed, though they work great as a fix for what I was 
having problems with, don't provide library functionality (only include 
what's needed).  Also, they require extra steps to use common 
implementations of automatic registration patterns in a library.



More information about the Binutils mailing list