* [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
@ 2003-04-11 3:43 Hal Black
2003-04-11 4:47 ` Alexandre Oliva
2003-04-11 8:16 ` Alan Modra
0 siblings, 2 replies; 17+ messages in thread
From: Hal Black @ 2003-04-11 3:43 UTC (permalink / raw)
To: binutils
[-- Attachment #1: Type: text/plain, Size: 1442 bytes --]
Using GNU ld version 2.13.90.0.18 20030206 (comes with Redhat 9)
Also experienced with previous 3.x and 2.9x versions.
When linking with a bunch of .o files, the desired behavior (static
initializers are called) happens. But when linking .a files composed of
those .o files, static initializers are not called. On the other hand,
when the .cpp files are combined to make a single .o file, which is then
used to form a .a file, that works.
This was previously reported to gcc bugs, but they sent me here (I've
been lurking for quite a while to see if it was okay to post bugs here):
http://gcc.gnu.org/cgi-bin/gnatsweb.pl (bug 7769)
There is some good discussion there.
Full source code and makefile follows in the attachment. See below for
a quick glance of what I'm talking about.
one.cc
------
#include <stdio.h>
class A {
public:
A() { printf("Hello world!\n"); }
};
A a;
------
two.cc
------
int main() {}
------
combined.cc
-----------
#include "one.cc"
#include "two.cc"
-----------
Makefile
--------
CPP=g++
test:main1 main2 main3 main4
./main1
./main2
./main3
./main4
%.o:%.cc
$(CPP) -c $<
lib%.a:%.o
ar rv $@ $<
both.a:one.o two.o
ar rv $@ $^
main1:one.o two.o
$(CPP) one.o two.o -o main1
main2:libone.a libtwo.a
$(CPP) libone.a libtwo.a -o main2
main3:both.a
$(CPP) both.a -o main3
main4:libcombined.a
$(CPP) libcombined.a -o main4
clean:
rm -f *.a *.o main*
--------
thanks for your time.
Hal
[-- Attachment #2: static_init.tar.bz2 --]
[-- Type: application/octet-stream, Size: 554 bytes --]
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
2003-04-11 3:43 [BUG] ld behavior varies for C++ static initializer depending on .a or .o input Hal Black
@ 2003-04-11 4:47 ` Alexandre Oliva
2003-04-12 4:01 ` Hal Black
2003-04-11 8:16 ` Alan Modra
1 sibling, 1 reply; 17+ messages in thread
From: Alexandre Oliva @ 2003-04-11 4:47 UTC (permalink / raw)
To: Hal Black; +Cc: binutils
On Apr 11, 2003, Hal Black <hablack@vt.edu> wrote:
> But when linking .a files composed
> of those .o files, static initializers are not called.
And, if you look closer, you'll notice the object files that contain
the initializers aren't linked in at all. Which is perfectly fine,
given that no symbols from it are referenced. Maybe you want
--whole-archive?
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist Professional serial bug killer
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
2003-04-11 3:43 [BUG] ld behavior varies for C++ static initializer depending on .a or .o input Hal Black
2003-04-11 4:47 ` Alexandre Oliva
@ 2003-04-11 8:16 ` Alan Modra
1 sibling, 0 replies; 17+ messages in thread
From: Alan Modra @ 2003-04-11 8:16 UTC (permalink / raw)
To: Hal Black; +Cc: binutils
On Thu, Apr 10, 2003 at 11:43:53PM -0400, Hal Black wrote:
> When linking with a bunch of .o files, the desired behavior (static
> initializers are called) happens. But when linking .a files composed of
> those .o files, static initializers are not called.
See http://sources.redhat.com/ml/binutils/2003-02/msg00155.html
--
Alan Modra
IBM OzLabs - Linux Technology Centre
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
2003-04-11 4:47 ` Alexandre Oliva
@ 2003-04-12 4:01 ` Hal Black
2003-04-12 5:43 ` Alexandre Oliva
0 siblings, 1 reply; 17+ messages in thread
From: Hal Black @ 2003-04-12 4:01 UTC (permalink / raw)
To: binutils
Alexandre Oliva wrote:
> On Apr 11, 2003, Hal Black <hablack@vt.edu> wrote:
>
>
>>But when linking .a files composed
>>of those .o files, static initializers are not called.
>
>
> And, if you look closer, you'll notice the object files that contain
> the initializers aren't linked in at all. Which is perfectly fine,
> given that no symbols from it are referenced. Maybe you want
> --whole-archive?
>
Thanks Alexandre, for replying and the --whole-archive tip - it works
great (has to be -Wl,-whole-archive when passed to g++, though, as noted
on the man page).
I still believe this is a bug, however. Even though there aren't any
references to static intializers, there is an implicit reference to
them. When using .o files, there are no references either, but the
static intializer is included in that case. Why should it be different
for a .a file with the same .o files in it? Should .a files not be used
for C++?
Perhaps the solution is to pass --whole-archive by default to ld when
linking with g++.
But, at least there is a workaround.
Thanks also to Alan for the reference, I don't know how I missed that
thread.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
2003-04-12 4:01 ` Hal Black
@ 2003-04-12 5:43 ` Alexandre Oliva
2003-04-12 14:24 ` Hal Black
0 siblings, 1 reply; 17+ messages in thread
From: Alexandre Oliva @ 2003-04-12 5:43 UTC (permalink / raw)
To: Hal Black; +Cc: binutils
On Apr 12, 2003, Hal Black <hablack@vt.edu> wrote:
> Why should it be different for a .a file with the same .o files in
> it? Should .a files not be used for C++?
Because .o files are copied to the output, whereas .a files are used
as libraries, i.e., only members that offer symbols that are being
looked for are copied to the output. Can you imagine the bloat if any
time you linked with a static library, all of the code in it was
copied to your executables?
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist Professional serial bug killer
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
2003-04-12 5:43 ` Alexandre Oliva
@ 2003-04-12 14:24 ` Hal Black
2003-04-12 16:52 ` Ian Lance Taylor
0 siblings, 1 reply; 17+ messages in thread
From: Hal Black @ 2003-04-12 14:24 UTC (permalink / raw)
To: binutils
Alexandre Oliva wrote:
> On Apr 12, 2003, Hal Black <hablack@vt.edu> wrote:
>
>
>>Why should it be different for a .a file with the same .o files in
>>it? Should .a files not be used for C++?
>
>
> Because .o files are copied to the output, whereas .a files are used
> as libraries, i.e., only members that offer symbols that are being
> looked for are copied to the output. Can you imagine the bloat if any
> time you linked with a static library, all of the code in it was
> copied to your executables?
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.
------------------
From the C++ draft spec 2 December 1996:
Section 3.7.1:
2 If an object of static storage duration has initialization or a
destructor with side effects, it shall not be eliminated even if it
appears to be unused, except that a class object or its copy may be
eliminated as specified in 12.8.
------------------
I would say that not looking for static initializers constitutes
eliminating them...
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
2003-04-12 14:24 ` Hal Black
@ 2003-04-12 16:52 ` Ian Lance Taylor
2003-04-12 18:01 ` Hal Black
0 siblings, 1 reply; 17+ messages in thread
From: Ian Lance Taylor @ 2003-04-12 16:52 UTC (permalink / raw)
To: Hal Black; +Cc: binutils
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, which would doubtless bring in other object files as well.
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. This would go against the very idea of a .a
file, which is that only required objects are included.
> I would say that not looking for static initializers constitutes
> eliminating them...
No, because they were never included in the first place.
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.
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.
Ian
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
2003-04-12 16:52 ` Ian Lance Taylor
@ 2003-04-12 18:01 ` Hal Black
2003-04-12 20:45 ` Alexandre Oliva
2003-04-13 22:55 ` Ian Lance Taylor
0 siblings, 2 replies; 17+ messages in thread
From: Hal Black @ 2003-04-12 18:01 UTC (permalink / raw)
To: binutils
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.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
2003-04-12 18:01 ` Hal Black
@ 2003-04-12 20:45 ` Alexandre Oliva
2003-04-13 2:11 ` Hal Black
2003-04-13 22:55 ` Ian Lance Taylor
1 sibling, 1 reply; 17+ messages in thread
From: Alexandre Oliva @ 2003-04-12 20:45 UTC (permalink / raw)
To: Hal Black; +Cc: binutils
On Apr 12, 2003, Hal Black <black@ieee.org> wrote:
>> That would mean that every static initializer in a .a file would be
>> brought in
> Yes, as desired.
Maybe in your specific application. But think of the Standard C++
library. It may contain hundreds, if not thousands, of global
initializers, that are of no use for most programs that don't happen
to use the particular feature that depend on some of these
initializers. Bringing them in just because you would like it to be
so is not exactly a reasonable proposition.
> 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?
No different from having it in an object file: if the object file is
linked in, the static initializer is run. The difference is that
object files listed in the command line are always linked in, whereas
those in a static library get linked in only if they would resolve
some symbol the linker is looking for.
> My claim is that if it has a static initializer, it is required.
If we implemented this mis-feature, you'll come back tomorrow and
complain about the bloat from all these modules being linked in that
are not needed for your program to run, and the answer will be that
they do contain static initializers so, per your request, they have to
be brought in.
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist Professional serial bug killer
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
2003-04-12 20:45 ` Alexandre Oliva
@ 2003-04-13 2:11 ` Hal Black
2003-04-14 18:41 ` Alexandre Oliva
0 siblings, 1 reply; 17+ messages in thread
From: Hal Black @ 2003-04-13 2:11 UTC (permalink / raw)
To: binutils
Alexandre Oliva wrote:
> On Apr 12, 2003, Hal Black <black@ieee.org> wrote:
>
>
>>>That would mean that every static initializer in a .a file would be
>>>brought in
>
>
>>Yes, as desired.
>
>
> Maybe in your specific application. But think of the Standard C++
> library. It may contain hundreds, if not thousands, of global
> initializers, that are of no use for most programs that don't happen
> to use the particular feature that depend on some of these
> initializers.
I'm not an expert on g++ symbols, but I'm assuming the static intializer
of the sort I'm talking about is is named
__static_initialization_and_detruction.* because that's what nm reports
for my test program.
When I run nm on libstdc++*.a and grep for static_initialization, I get
not thousands, not hundreds, but zero matches. So, if I'm right about
the naming, the program would get no bigger if the changes I suggested
were implemented.
OTOH, I could be totally wrong. 8') I really know nothing about the
details of how g++ does naming of C++ constructs.
[caveat: I don't have access to the latest stuff right now, this is with
mandrake 9.0 - maybe they have added thousands of static initializers
since then]
I counted 18 static initializers total in /usr/lib. I don't know
whether these are meant to be called every time the library is linked
against, or just when a certain feature is used.
> Bringing them in just because you would like it to be
> so is not exactly a reasonable proposition.
It's not a question of me liking it to be so. I have already stated
that I am fine with the work around. I am raising the point how the C++
spec is interpreted in terms of libraries for discussion. The way to
dispute this point is to argue against the point, not wave it off
because you infer endearment of an individual to it, which is irrelevant
on whether it is the right way to do it or not.
I just hadn't heard any valid reasons against having it be as I
describe, and it seems like the correct interpretation of the spec.
>>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?
>
>
> No different from having it in an object file: if the object file is
> linked in, the static initializer is run. The difference is that
> object files listed in the command line are always linked in, whereas
> those in a static library get linked in only if they would resolve
> some symbol the linker is looking for.
I understand the behavior of the tools. What I asked was what is the
meaning of having objects with static storage in a library.
Based on an earlier portion of your reply, I am taking your
interpretation to mean that a static initializer in a library is only
called when something references an instance of its class or members,
but not otherwise. I don't believe this is a valid view from reading
the C++ spec.
>>My claim is that if it has a static initializer, it is required.
>
>
> If we implemented this mis-feature, you'll come back tomorrow and
> complain about the bloat from all these modules being linked in that
> are not needed for your program to run, and the answer will be that
> they do contain static initializers so, per your request, they have to
> be brought in.
If they were not needed for the program to run, the behavior (not
counting performance/memory footprint for the moment) would be the same
whether they were included or not. Desired side-effects of the static
initializers don't happen when they're not included, therefore they are
required for the program to run.
I see your point that if the custom is to put in instances of static
storage whose initializers aren't meant to be called all the time, some
uneccesary bloat could result. If they are supposed to be called,
however, they aren't unneccesary.
I don't know whether the 18 static initializers in my /usr/lib are meant
to be used the way I describe or the way you describe, so I can't say
whether these are unneccesary or neccesary.
Regardless, if my interpretation of the C++ spec is correct, it is a
flaw in the library to create static storage items with initializers
with side effects that aren't meant to be run for all users of the
library. In that case, the linker would be following the spec and would
deserve no complaints. It's not the auto-maker's fault if the car is
working fine and you get caught speeding.
But, if you don't want to implement it to avoid complaints, it's your
project, not mine, so I can't argue with that.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
2003-04-12 18:01 ` Hal Black
2003-04-12 20:45 ` Alexandre Oliva
@ 2003-04-13 22:55 ` Ian Lance Taylor
2003-04-13 23:07 ` Zack Weinberg
2003-04-14 5:14 ` Hal Black
1 sibling, 2 replies; 17+ messages in thread
From: Ian Lance Taylor @ 2003-04-13 22:55 UTC (permalink / raw)
To: Hal Black; +Cc: binutils
Hal Black <black@ieee.org> writes:
> > 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.
No Unix linker has ever worked that way.
Basically, you misunderstand how ld and ar work. If you feel that you
have been misled by existing documentation, please let us know so that
we can fix it.
Also, while this is not the reason for not making the change, it turns
out that it is not an efficient change to make. It would require the
linker to examine every object in every archive, which obviates the
entire point of having archives in the first place. Again, this
inefficiency, while severe, is not the reason for not making the
change; the reason for not making the change is that ld and ar
implement behaviour which has not changed for decades, and should not
be changed now.
Ian
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
2003-04-13 22:55 ` Ian Lance Taylor
@ 2003-04-13 23:07 ` Zack Weinberg
2003-04-13 23:15 ` Ian Lance Taylor
2003-04-13 23:26 ` Ulrich Drepper
2003-04-14 5:14 ` Hal Black
1 sibling, 2 replies; 17+ messages in thread
From: Zack Weinberg @ 2003-04-13 23:07 UTC (permalink / raw)
To: binutils; +Cc: black
Ian Lance Taylor <ian@airs.com> writes:
> Hal Black <black@ieee.org> writes:
>> 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.
>
> No Unix linker has ever worked that way.
>
> Basically, you misunderstand how ld and ar work. If you feel that you
> have been misled by existing documentation, please let us know so that
> we can fix it.
I'd like to point out that while this is true for static (.a)
libraries, it is not true for shared (.so) libraries -- the linker
generates DT_NEEDED entries for every shared library on the command
line, whether or not they satisfy undefined symbols. Personally I
consider this a bug.
zw
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
2003-04-13 23:07 ` Zack Weinberg
@ 2003-04-13 23:15 ` Ian Lance Taylor
2003-04-13 23:26 ` Ulrich Drepper
1 sibling, 0 replies; 17+ messages in thread
From: Ian Lance Taylor @ 2003-04-13 23:15 UTC (permalink / raw)
To: Zack Weinberg; +Cc: binutils, black
Zack Weinberg <zack@codesourcery.com> writes:
> Ian Lance Taylor <ian@airs.com> writes:
>
> > Hal Black <black@ieee.org> writes:
> >> 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.
> >
> > No Unix linker has ever worked that way.
> >
> > Basically, you misunderstand how ld and ar work. If you feel that you
> > have been misled by existing documentation, please let us know so that
> > we can fix it.
>
> I'd like to point out that while this is true for static (.a)
> libraries, it is not true for shared (.so) libraries -- the linker
> generates DT_NEEDED entries for every shared library on the command
> line, whether or not they satisfy undefined symbols. Personally I
> consider this a bug.
I think that one is debatable. It's certainly true that shared
libraries and archive libraries don't work the same way; as you say,
one obvious difference is in fact the very one we are talking
about--all static initializers in a shared library are run, whether
they are required or not. There are a number of other
differences--only in simple case can you just replace a .a file with a
.so file.
I think the general attitude of linker implementors has been that if
you list a shared library on the command line, you must want it in
there. That is, a .so file is in that sense more like a .o file than
a .a file.
But I agree that it could be argued the other way. I don't know of
any ELF linker which does not generate a DT_NEEDED for a .so listed on
the command line, but perhaps there is one.
Ian
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
2003-04-13 23:07 ` Zack Weinberg
2003-04-13 23:15 ` Ian Lance Taylor
@ 2003-04-13 23:26 ` Ulrich Drepper
1 sibling, 0 replies; 17+ messages in thread
From: Ulrich Drepper @ 2003-04-13 23:26 UTC (permalink / raw)
To: Zack Weinberg; +Cc: binutils, black
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Zack Weinberg wrote:
> I'd like to point out that while this is true for static (.a)
> libraries, it is not true for shared (.so) libraries -- the linker
> generates DT_NEEDED entries for every shared library on the command
> line, whether or not they satisfy undefined symbols. Personally I
> consider this a bug.
Agreed, I argued like that for years. If somebody wants the DSO
included s/he can use -u to create and artificial dependency.
- --
- --------------. ,-. 444 Castro Street
Ulrich Drepper \ ,-----------------' \ Mountain View, CA 94041 USA
Red Hat `--' drepper at redhat.com `---------------------------
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)
iD8DBQE+mfH72ijCOnn/RHQRAtHmAKCnq3OcfkKWRnvmmZI9cyTLCzkeGgCfej6g
ZErCJSskzy+8TJD3Ld+CWos=
=9jUv
-----END PGP SIGNATURE-----
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
2003-04-13 22:55 ` Ian Lance Taylor
2003-04-13 23:07 ` Zack Weinberg
@ 2003-04-14 5:14 ` Hal Black
2003-04-14 5:30 ` Ian Lance Taylor
1 sibling, 1 reply; 17+ messages in thread
From: Hal Black @ 2003-04-14 5:14 UTC (permalink / raw)
To: binutils
Ian Lance Taylor wrote:
> Hal Black <black@ieee.org> writes:
>
>
>>>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.
>
>
> No Unix linker has ever worked that way.
Well, for most of the lifetime of Unix, there were no static
initializers, since there was no C++, so this is not surprising.
> Also, while this is not the reason for not making the change, it turns
> out that it is not an efficient change to make. It would require the
> linker to examine every object in every archive, which obviates the
> entire point of having archives in the first place. Again, this
> inefficiency, while severe, is not the reason for not making the
> change; the reason for not making the change is that ld and ar
> implement behaviour which has not changed for decades, and should not
> be changed now.
For the C code that ld has been linking for decades, I agree with you 100%.
But, C++ has additional requirements. Either the tool needs to change
to meet these requirements, or a different tool needs to be used to meet
them.
If .a is meant only for what it has been used for decades without
changing to accomodate the full C++ specification, you're right, I
misunderstood the usage for it. That is definately not what I want.
Based on the other replies, I guess that .so can be used to acheive the
desired behavior even though it includes too much.
Anyway, thank you for responding and for your time, Ian.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
2003-04-14 5:14 ` Hal Black
@ 2003-04-14 5:30 ` Ian Lance Taylor
0 siblings, 0 replies; 17+ messages in thread
From: Ian Lance Taylor @ 2003-04-14 5:30 UTC (permalink / raw)
To: Hal Black; +Cc: binutils
Hal Black <black@ieee.org> writes:
> > No Unix linker has ever worked that way.
>
> Well, for most of the lifetime of Unix, there were no static
> initializers, since there was no C++, so this is not surprising.
C++ has had static initializers at least since 1985, so it's not all
that new.
> If .a is meant only for what it has been used for decades without
> changing to accomodate the full C++ specification, you're right, I
> misunderstood the usage for it. That is definately not what I
> want. Based on the other replies, I guess that .so can be used to
> acheive the desired behavior even though it includes too much.
I'm not sure in what sense a .so file includes too much. A .so file
is a very rough replacement for a .a file, so the fact that it
includes everything which is in the .a file is a feature. It's true
that a .so file will always run all the static initializers which are
found in the .a file, but that's the very feature you want to
implement. There are various differences in the implementation of
common symbols, but C++ disallows common symbols so that shouldn't
matter too much. Warning symbols no longer work correctly, but that
is a GNU extension anyhow. A .so is admittedly slightly slower, but
that rarely matters these days.
So what are your concerns with using a .so?
Ian
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
2003-04-13 2:11 ` Hal Black
@ 2003-04-14 18:41 ` Alexandre Oliva
0 siblings, 0 replies; 17+ messages in thread
From: Alexandre Oliva @ 2003-04-14 18:41 UTC (permalink / raw)
To: Hal Black; +Cc: binutils
On Apr 12, 2003, Hal Black <black@ieee.org> wrote:
> I'm not an expert on g++ symbols, but I'm assuming the static
> intializer of the sort I'm talking about is is named
> __static_initialization_and_detruction.* because that's what nm
> reports for my test program.
Watch out for .ctor, .init or .init_array sections as well.
> I just hadn't heard any valid reasons against having it be as I
> describe, and it seems like the correct interpretation of the spec.
I disagree. The compiler, which is the entity that deals with
translation units, isn't dropping any initializers, just like mandated
by the spec. Now, by the Standard, a program is one or more
translation units linked together [basic.link], and that's it.
Nowhere does it get into details of what a linker is, nevermind how
static archives should behave, since this is all far beyond the scope
of the C++ Standard.
Your point that archives should be scanned for initializers would be
perfectly reasonable, except for the bloat one wouldn't be able to
avoid, but, like Ian says, this is not the way linkers have dealt with
archives in the past and, barring a strong reason to change, they
should change. Standard compliance is not such a reason, because the
nowhere does the standard determine how to select the translation
units that go into a program.
> Based on an earlier portion of your reply, I am taking your
> interpretation to mean that a static initializer in a library is only
> called when something references an instance of its class or members,
> but not otherwise. I don't believe this is a valid view from reading
> the C++ spec.
My interpretation is that a static initializer in a translation unit
is only executed if the translation unit makes it to the program. The
point under debate is whether the translation unit must make it to the
program in spite of not being referenced by any other translation unit
listed in the program. If you have such requirements, using an
archive is the wrong approach: you want to list the object files
instead.
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist Professional serial bug killer
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2003-04-14 18:41 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-04-11 3:43 [BUG] ld behavior varies for C++ static initializer depending on .a or .o input Hal Black
2003-04-11 4:47 ` Alexandre Oliva
2003-04-12 4:01 ` Hal Black
2003-04-12 5:43 ` Alexandre Oliva
2003-04-12 14:24 ` Hal Black
2003-04-12 16:52 ` Ian Lance Taylor
2003-04-12 18:01 ` Hal Black
2003-04-12 20:45 ` Alexandre Oliva
2003-04-13 2:11 ` Hal Black
2003-04-14 18:41 ` Alexandre Oliva
2003-04-13 22:55 ` Ian Lance Taylor
2003-04-13 23:07 ` Zack Weinberg
2003-04-13 23:15 ` Ian Lance Taylor
2003-04-13 23:26 ` Ulrich Drepper
2003-04-14 5:14 ` Hal Black
2003-04-14 5:30 ` Ian Lance Taylor
2003-04-11 8:16 ` Alan Modra
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).