Initialization of unused global variables from static libraries.

A

Alf P. Steinbach

* Keith H Duggar:
Eh, I'm not sure I would call such schemes "esoteric". Function
level linking and other smart linking techniques are valuable
optimization tools. I've /wished/ that gnu supported this out
of the box.

Utility aside, what in the standard /guarantees/ that all static
objects in a TU are "part of the program" if /any/ symbol in that
TU is referenced?

As already discussed, the standard doesn't use that term "part of the program"
except for denoting a region of text, which wrt. this issue is irrelevant.

§2/1, §2/2 and §2.1 (complete section) are the relevant parts for what
constitutes a program.

§1.4/6 explains what §2.1 is about, ...

"combining translation units to form a complete C++ program (2.1)"

.... so that's what a complete C++ program is, created by /combining translation
units/ according to §2.1.

AFAIK the standard doesn't talk about any lesser unit anywhere.

So the very clear §3.7.1/2 (about how static lifetime objects with side-effect
in initialization or destrution cannot be eliminated) is either talking about
static lifetime objects in the translation units that are combined to form the
program according to §2.1, or it's meaningless, trying to trick us by hinging
the text on a weasel phrase. Which is likely? I think not the latter. :)

I certainly believe that the transitive closure of symbols is
part of the program, but all them? Just because they happen to
be in the same TU? Where is this guarantee?

§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".

By the way, considering your q. I'm revising my view of this for the second
time. I now think Pete was wrong to focus so strongly on the phrase "library
component" in §2.1/1-9 and interpret "library component" as a part of the
translated program text -- if he did. I now think the key word in paragraph 9
is *external*, and considering that paragraph 8 has already combined the
translation units (at least that's a possible and consistent interpretation of
"are combined as follows"), what's left in paragraph 9 is things /external to
the program/ that has now been formed by combining translation units, e.g.
references to functions in the runtime library and operating system API.

I think it's good to have this hashed out in detail.

Even it it should turn out that my new view of paragraph 9 is wrongo...



Cheers & hth.,

- Alf
 
A

Alf P. Steinbach

* Paul Bibbings:
Alf P. Steinbach said:
* Paul Bibbings:
But Alf, I understood from the discussion so far that there is indeed
only a requirement that code that is required is linked in, to satisfy
external references; that, whilst it /is/ the case that g++ will link in
a whole translation unit (object file) from a library, that this is
indeed implementation dependent - that there is no requirement that it
do so. Hence, for portability reason, I would say that Milan's concern
is a valid one.

As Pete referenced in an earlier post:

[lex.phases] 2.2/1-9
"All external entity references are resolved. Library components are
linked to satisfy external references to entities not defined in the
current translation. ..."

It is only the fact that g++ is not applying a "smart linking" model -
bringing in *only* what is required to satisfy external references -
that the kind of initialization that Milan is looking for is not
guaranteed. As has been seen, g++ can guarantee this as an
implementation detail, but the Standard doesn't require it, as long as
external references are satisfied.
Hm, let's be careful so as not to misrepresent Pete.

Of course.
Here's the last thing he wrote in this thread:

Okay. That's clear. I must have missed that. Then there does appear
to be a guarantee here. Do we have a reference to this yet?

Yes.

§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".

And, by
`this', I mean specifically that all static objects in a library
translation unit are linked in, even where they are not referenced
directly;

No, not all: only those that can't be eliminated according to the above are
guaranteed to be linked in by a standard-conforming implementation.

that is, that the behaviour we have seen so far for the
examples as g++ compiles them is guaranteed. (Not that I'm doubting the
claim, in any sense, of course.)


Cheers & hth.,

- Alf
 
P

Paul Bibbings

Alf P. Steinbach said:
* Paul Bibbings:

Yes.

§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".

Right. So. If we bring back the extension of the OPs code that I
introduced in an early post to this thread ...

// file: b.cc
#include <iostream>

void baz() { }

bool foo()
{
std::cout << "foo" << std::endl;
return true;
}

const bool bar = foo();

// file: a.cc
void baz();

int main()
{
baz();
return 0;
}

22:07:28 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/nano $g++ -c a.cc b.cc

22:07:46 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/nano $ar rcs libb.a b.o

22:07:58 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/nano $g++ -L. a.o -o a2 -lb

22:08:11 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/nano $./a2
foo

.... here, neither foo nor bar (in libb.a:b.o) is directly referenced
from the program code, but nevertheless foo() is called since bar -
which is of static storage duration - is initialized. The references
from the Standard, particularly §3.7.1/2, seem to support that this can
be taken as a guarantee in this instance. Is that what we're saying here?

Regards

Paul Bibbings
 
K

Keith H Duggar

* Keith H Duggar:








As already discussed, the standard doesn't use that term "part of the program"
except for denoting a region of text, which wrt. this issue is irrelevant..

2/1, 2/2 and 2.1 (complete section) are the relevant parts for what
constitutes a program.

1.4/6 explains what 2.1 is about, ...

    "combining translation units to form a complete C++ program (2.1)"

... so that's what a complete C++ program is, created by /combining translation
units/ according to 2.1.

AFAIK the standard doesn't talk about any lesser unit anywhere.

So the very clear 3.7.1/2 (about how static lifetime objects with side-effect
in initialization or destrution cannot be eliminated) is either talking about
static lifetime objects in the translation units that are combined to form the
program according to 2.1, or it's meaningless, trying to trick us by hinging
the text on a weasel phrase. Which is likely? I think not the latter. :)

Ok cool. Fortunately the standard is clear (correct me if I'm wrong)
that functions are not objects. So function level linking is still
possible in a conformant platform.

KHD
 
K

Keith H Duggar

Yes Herb I realize that and in this instance I made a mistake and
apologized. It is worth noting however that nobody should be above
criticism and we all make mistakes. Some things Bjarne Stroustrup says I
disagree with.

Nobody cares what you disagree with /unless/ he can present
cogent arguments. And that is something you habitually fail
to do.

Notice that in this thread, despite his stature, Pete Becker
presented rational arguments for his view as did Alf. In the
end this yielded better understanding for all involved as well
as bystanders. This is no less than what one expects in a
technical discussion ie rational discussion from ALL.

If that is expected (or at least hoped for) from even those of
greatest authority, what do you think it expected from you? Eh
well, I guess at this point not much honestly. (But maybe some
of us still hope. I know I do. Because I don't think you are a
troll but rather a terrified adolescent fool.)

KHD
 
J

Jorgen Grahn

Interestingly it only seems to work on VC++ if the unrelated function you
call is in the same TU as the initialization code which kind of makes
sense...

That's what I'd expect on Unix, too. I see a static library as a bunch
of object files. Some are needed, some aren't, and the latter aren't
linked in.

/Jorgen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top