This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: c++/7769: using static libraries sometimes loses static initialization
- From: Hal Black <black at ieee dot org>
- To: bangerth at dealii dot org, gcc-bugs at gcc dot gnu dot org, gcc-prs at gcc dot gnu dot org,hablack at vt dot edu, nobody at gcc dot gnu dot org, gcc-gnats at gcc dot gnu dot org
- Date: Thu, 19 Dec 2002 22:22:28 -0500
- Subject: Re: c++/7769: using static libraries sometimes loses static initialization
- References: <20021220014005.15538.qmail@sources.redhat.com>
bangerth@dealii.org wrote:
Synopsis: using static libraries sometimes loses static initialization
State-Changed-From-To: open->closed
State-Changed-By: bangerth
State-Changed-When: Thu Dec 19 17:40:05 2002
State-Changed-Why:
This is not a bug. When you want that a particular
object file (possibly within an archive) is pulled into you
executable for sure, then you have to reference an object
inside it.
This is a bug.
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. [hwb: see ** below]
This is talking about the storage of the object, but storage implies
initialization (and destruction).
I would quote from the official spec but it costs $18. 8')
From the common sense perspective, a simple piece of code like this
shouldn't >execute< differently based on how you call the linker.
If you rename your class "A" to "ComplexClass", to make
its symbols better visible in the executable, you
see that the object file with the static constructor
is not even pulled into the executable:
g/static_init> nm main1 | grep ComplexClass
080485f0 W __12ComplexClass
g/static_init> nm main2 | grep ComplexClass
g/static_init> nm main3 | grep ComplexClass
g/static_init> nm main4 | grep ComplexClass
080485f0 W __12ComplexClass
I guess this is just how the linker works.
Correct, the compiler is fine, it is the linker that is not working
correctly under the circumstances described above.
W.
http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=7769
Anyway, thanks for your time.
**(Here is the referenced section from 12.8, which does not apply -
we're not making any copies):
Whenever a class object is copied and the original object and the copy
have the same type, if the implementation
can prove that either the original object or the copy will never again
be used except as the result of an
implicit destructor call (12.4), an implementation is permitted to treat
the original and the copy as two different
ways of referring to the same object and not perform a copy at all. In
that case, the object is
destroyed at the later of times when the original and the copy would
have been destroyed without the optimization.
109) [Example:
class Thing {
public:
Thing();
~Thing();
Thing(const Thing&);
Thing operator=(const Thing&);
void fun();
};
void f(Thing t) { }
void g(Thing t) { t.fun(); }
int main()
{
Thing t1, t2, t3;
f(t1);
g(t2);
g(t3);
t3.fun();
}
Here t1 does not need to be copied when calling f because f does not use
its formal parameter again after
copying it. Although g uses its parameter, the call to g(t2) does not
need to copy t2 because t2 is not
used again after it is passed to g. On the other hand, t3 is used after
passing it to g so calling g(t3) is
required to copy t3. ]