Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Initialization of unused global variables from static libraries.

Reply
Thread Tools

Initialization of unused global variables from static libraries.

 
 
Keith H Duggar
Guest
Posts: n/a
 
      04-19-2010
On Apr 19, 1:32 pm, Pete Becker <(E-Mail Removed)> wrote:
> Alf P. Steinbach wrote:
>
> > Then §3.7.1/2 applies to those objects, but do you have a reference in
> > the standard for which objects /are/ "part of the program"?

>
> "Phases of translation", [lex.phases], paragraph 1, bullet 9 describes
> which library components become part of the program.
>
> This is essentially a description of standard linker technology: link in
> all the object files, then thumb through the libraries to resolve
> unsatisfied external references.


Is "external usage" transitive? For example given

<code>
//in foolib/foo.cpp
bool fooInit ( ) { ... }
....
bool const TheInitDone = fooInit() ;
....
void foodo ( )
{
if ( TheInitDone ) {
...
} else {
abort() ;
}
}

//in main.cpp
int main ( )
{
foodo() ;
return 0 ;
}
</code>

"foodo" is "externally used" so its definition would be "part of
the program". Would this transitively make TheInitDone "externally
used" and therefore part of the program and thus fooInit as well?

Thanks again. This is huge. Can't believe I've been ignorant of
this subtlety all these years. Hmm I wonder if that core dump back
back in 2006 ...

KHD
 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      04-19-2010
* Öö Tiib:
> On Apr 19, 8:19 pm, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
>> * Pete Becker:
>>
>>> Alf P. Steinbach wrote:
>>>> * Pete Becker:
>>>>> Alf P. Steinbach wrote:
>>>>>> Especially considering that §3.7.1/2 only makes a difference for an
>>>>>> object that is not referenced, or "unused" as it says, -- that
>>>>>> that's what it's specifically about.
>>>>>> If it doesn't apply to the "unused" objects it says that it applies
>>>>>> to, then what?
>>>>> "Unused" objects are objects that are part of the program but not
>>>>> "used".
>>>> I can't find the qualification "are part of the program" in the standard.
>>> Of course not. It's implicit in every part of the standard. The standard
>>> doesn't need to say that the foo.obj on my hard drive is not part of
>>> your program. It does need to say when and which objects and functions
>>> in libraries are part of the program, and it does that.

>> I don't understand. The first sentence says that "Of course" I can't find it in
>> the standard, whereas the last sentence says that "it does [say which object and
>> functions ... are part of the program]", which apparenly is self-contradictory.
>> Where does the standard say this?

>
> I think that closest thing is in 2.1/9 that mentions what will be
> taken from library. But it feels that there you are back in round 1
> interpreting these vague words. For me it means that library component
> (probably translation unit in library?) is not linked into program
> unless it satifies external references that are not yet resolved.


Yes, that's also how I read it.

E.g., if this is put in a library, and then linked, ...

#include <stdio.h>
int const x = printf( "blah blah\n" );
int main() {}

.... then I do not expect any difference from having it in an object file and
linking that object file, i.e. I do expect the output "blah blah" no matter the
physical packaging of the object code, be it in an object file, a library or
some other kind of repository, or even the Windows clipboard (TFSM forbid).

And assuming that the standard indeed requires the same result for the code
above regardless of the intermediate steps of the build, then if there is some
loophole where unreferenced static lifetime objects in libraries can be freely
eliminated, then one would need the special casing of the TU containing "main"
that Pete mentioned, "it is part of the program (here, because it's in the same
translation unit as main)", and that I can't find anywhere in the standard.


Cheers,

- Alf
 
Reply With Quote
 
 
 
 
Milan Radovich
Guest
Posts: n/a
 
      04-19-2010
On Mon, 19 Apr 2010 15:21:38 +0200, "Alf P. Steinbach" <(E-Mail Removed)> wrote:

>I'd try an object with a constructor.
>


Unfortunately the results are similar. Seems like there is no choice but
turning to implementation-specific linker options.
 
Reply With Quote
 
Milan Radovich
Guest
Posts: n/a
 
      04-19-2010
On Mon, 19 Apr 2010 10:42:19 -0400, Pete Becker <(E-Mail Removed)> wrote:

>"Unused" objects are objects that are part of the program but not "used".
>
>static my_type m;
>
>int main()
>{
>return 0;
>}
>
>Although 'm' is unused, it is part of the program (here, because it's in
>the same translation unit as main) and it has to be constructed and
>destroyed.
>
>But if you put 'm' into a library, it's not part of the program unless
>there is an external reference to it in the program. That's the point of
>libraries: if you don't use it (in the colloquial sense) it doesn't have
>to get linked in. If that weren't the case, "Hello, world" would have to
>pull in the entire standard library.


If I understand correctly, then according to that interpretation if a static
library has more than one entity: for example, in addition to the original
foo/bar it defines function f(), then even if f() is used in the main program,
it still would be correct if "foo" is not printed, even though implementations
I have do print "foo" in this case.
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      04-19-2010
* Pete Becker:
> Alf P. Steinbach wrote:
>>
>> E.g., if this is put in a library, and then linked, ...
>>
>> #include <stdio.h>
>> int const x = printf( "blah blah\n" );
>> int main() {}
>>
>> ... then I do not expect any difference from having it in an object
>> file and linking that object file, i.e. I do expect the output "blah
>> blah" no matter the physical packaging of the object code, be it in an
>> object file, a library or some other kind of repository, or even the
>> Windows clipboard (TFSM forbid).
>>

>
> That works because the implementation's startup code calls main, so
> there's an external reference to main, which the linker resolves by
> linking in that code.


Then it seems that we're up against the old
initialization-deferred-till-after-first-statement-of-main, where it only needs
to be done before the first call to or reference of (I can't recall exactly)
something in the TU.

Checking...

Yep, when I added a dummy function 'init' to the OP's B translation unit, and
called that dummy from A (main), then


<result>
C:\test> gnuc -c b.cpp

C:\test> gnuc -c a.cpp

C:\test> del *.a

C:\test> ar -r knurre.a b.o
ar: creating knurre.a

C:\test> gnuc a.o knurre.a

C:\test> a
foo

C:\test> _
</result>


So it wasn't that the static object wasn't referenced, it was that nothing in
the "main" TU referred to /anything at all/ in that TU. And the "main" TU is
referred to implicitly by "main" being referred to by the runtime. Although wrt.
to the formal that's not an argument that holds water, but it must be so.

Not sure if that's what you've been trying to say all the time?


Cheers,

- Alf
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      04-19-2010
On Apr 19, 8:55*pm, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
> * Öö Tiib:
>
>
>
>
>
> > On Apr 19, 8:19 pm, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
> >> * Pete Becker:

>
> >>> Alf P. Steinbach wrote:
> >>>> * Pete Becker:
> >>>>> Alf P. Steinbach wrote:
> >>>>>> Especially considering that §3.7.1/2 only makes a difference for an
> >>>>>> object that is not referenced, or "unused" as it says, *-- *that
> >>>>>> that's what it's specifically about.
> >>>>>> If it doesn't apply to the "unused" objects it says that it applies
> >>>>>> to, then what?
> >>>>> "Unused" objects are objects that are part of the program but not
> >>>>> "used".
> >>>> I can't find the qualification "are part of the program" in the standard.
> >>> Of course not. It's implicit in every part of the standard. The standard
> >>> doesn't need to say that the foo.obj on my hard drive is not part of
> >>> your program. It does need to say when and which objects and functions
> >>> in libraries are part of the program, and it does that.
> >> I don't understand. The first sentence says that "Of course" I can't find it in
> >> the standard, whereas the last sentence says that "it does [say which object and
> >> functions ... are part of the program]", which apparenly is self-contradictory.
> >> Where does the standard say this?

>
> > I think that closest thing is in 2.1/9 that mentions what will be
> > taken from library. But it feels that there you are back in round 1
> > interpreting these vague words. For me it means that library component
> > (probably translation unit in library?) is not linked into program
> > unless it satifies external references that are not yet resolved.

>
> Yes, that's also how I read it.
>
> E.g., if this is put in a library, and then linked, ...
>
> * *#include <stdio.h>
> * *int const x = printf( "blah blah\n" );
> * *int main() {}
>
> ... then I do not expect any difference from having it in an object file and
> linking that object file, i.e. I do expect the output "blah blah" no matter the
> physical packaging of the object code, be it in an object file, a library or
> some other kind of repository, or even the Windows clipboard (TFSM forbid).
>
> And assuming that the standard indeed requires the same result for the code
> above regardless of the intermediate steps of the build, then if there is some
> loophole where unreferenced static lifetime objects in libraries can be freely
> eliminated, then one would need the special casing of the TU containing "main"
> that Pete mentioned, "it is part of the program (here, because it's in the same
> translation unit as main)", and that I can't find anywhere in the standard.


Yes, 3.6.1. as "int main(int argc, char* argv[])" or "int main()" must
be defined somewhere. That together with discriminating to poor
translation units that are in library 2.1/9 is perhaps the ground of
selection.

So:
main is one of external references that must be resolved.
Anything in same translation unit with main must be resolved as well.
References from vagabond translation units that are not tied into
libraries but are linked must be resolved.
When some translation unit from library is taken to resolve things
then again, what it leaves unresolved should be resolved.


 
Reply With Quote
 
Keith H Duggar
Guest
Posts: n/a
 
      04-19-2010
On Apr 19, 2:22 pm, Pete Becker <(E-Mail Removed)> wrote:
> Keith H Duggar wrote:
> > On Apr 19, 1:32 pm, Pete Becker <(E-Mail Removed)> wrote:

>
> >> This is essentially a description of standard linker technology: link in
> >> all the object files, then thumb through the libraries to resolve
> >> unsatisfied external references.

>
> > Is "external usage" transitive? For example given

>
> Well, yes, sort of. <g> Unix linkers typically made a single pass
> through the list of library files, and if there were still unresolved
> symbols they reported an error and quit. So you sometimes had to list
> the same library file several times on the command line. These days they
> pretty much know to go through everything, repeating until all external
> references have been resolved, or until no new files have been linked
> in; in the latter case, the unresolved symbols are reported as not found.


I haven't tested it with 4.0 gnu but with 3.3 it was still the
case that it was single pass through the /list/ of files but it
would resolve transitively all symbols within each lib file. So
one still had to list libraries more than once but only to
resolve transitivity /between/ different libraries.

Was their a time when Unix linkers would not even transitively
resolve /within/ a single library?

Sorry for being thick, but you can please confirm that for my
exmaple

<code>
//in foolib/foo.cpp
bool fooInit ( ) { return true ; }
....
bool const TheInitDone = fooInit() ;
....
void foodo ( )
{
if ( TheInitDone ) {
...
} else {
abort() ;
}
}

//in main.cpp
int main ( )
{
foodo() ;
return 0 ;
}
</code>

a conforming C++ platform must either 1) dynamically initialize
TheInitDone by calling fooInit() or 2) fail to produce a program.
Or put another way, given the code above, the main's foodo() call
cannot trigger the foodo() abort for a conforming platform?

KHD
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      04-20-2010
* Alf P. Steinbach:
> * Milan Radovich:
>> Hello,
>>
>> I have 2 files:
>>
>> a.cc:
>> ---------------------------------------
>> int main()
>> {
>> return 0;
>> }
>> ---------------------------------------
>>
>> b.cc:
>> ---------------------------------------
>> #include <iostream>
>>
>> bool foo()
>> {
>> std::cout << "foo" << std::endl;
>> return true;
>> }
>>
>> const bool bar = foo();
>> ---------------------------------------
>>
>> If I compile the application like that:
>>
>> g++ -c a.cc b.cc
>> g++ a.o b.o -o a
>>
>> then when application is executed, it outputs a string "foo".
>>
>> But if I create a static library from b.cc and then link application
>> with that library, like that:
>>
>> g++ -c a.cc b.cc
>> ar rcs libb.a b.o
>> g++ -L. -lb a.o -o a2
>>
>> then when application is ran, it doesn't print anything.
>>
>> After I searched for the reason why this happens, I found that
>> when linking with static libraries, linker omits code which is not
>> reachable through any execution path.
>>
>> The question is:
>>
>> 1) Is it a correct behaviour according to a Standard?

>
> No, regardless of how the code is physically packaged.
>
> §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".
>
> §12.8 then talks about elimination of copy constructor calls, in
> §12.8/15, which is not your case.


As it turned out by discussion with Pete Becker, I was wrong about this.

Hm, I can't even blame lack of coffee, even though I was a bit tired. Well,
that's enough. Good excuse! Bad extra defense: now that some wool has been
removed I recall writing about this problem earlier, at length. Oh well.

The crucial insight is that only translation units that are somehow referenced
by code, need to be included in the final program, and that §3.7.1 and the rest
of the standard only applies to code in the actually included TU's.

Translation unit [a.cc] is referenced & therefore included by virtue of
containing "main", but there's no reference to anything in [b.cc].

So, a simple fix is to reference something in [b.cc], e.g. a call of some dummy
function there.

Pitfall for the simple fix: the standard's §3.6.2/3 supports deferring the
dynamic initialization of statics in a TU until the first call of a function or
reference of an object in the TU. This can play havoc with using e.g. a factory
where types have installed themselves via the dynamic initialization of statics
in their translation units, if the use of the factory occurs before the first
call of a function or reference of object in some self-registering type's TU.


>> 2) Is there is a pattern which forces linker to add such a code to an
>> executable?

>
> I'd try an object with a constructor.


I'd now instead try to reference something in the TU.


Cheers & hth.,

- Alf
 
Reply With Quote
 
Fred Zwarts
Guest
Posts: n/a
 
      04-20-2010
"Pete Becker" <(E-Mail Removed)> wrote in message
news(E-Mail Removed)
> Fred Zwarts wrote:
>> "Pete Becker" <(E-Mail Removed)> wrote in message
>> news:(E-Mail Removed)
>>> Fred Zwarts wrote:
>>>> Interesting. What is the definition of a library component?
>>> It's not defined. The old Unix rule was that each source file gets
>>> compiled into an object file, and each object file is a single
>>> entity: either it gets linked in in its entirety, or it doesn't get
>>> linked in. Some compilers produce object files with finer
>>> granularity: the linker can pull in only the parts that are
>>> actually needed, and ignore other parts of the object file.
>>>
>>>> Assuming that a library component is a translation unit:
>>>> If a library component is linked in, should it be linked in
>>>> completely, or is it also allowed to link in only those parts from
>>>> a library component that satisfy external references?
>>> Yes. <g>

>>
>> If the term "library component" is not defined,
>> then the question could equally well be answered with No.
>>
>> But, as C++ talks in terms of translation units, I think that the
>> linker
>> should not eliminate parts of a unit, execpt if it can deduce that
>> it has no effect on the execution of a program.

>
> If that was the intention, the wording would have been about
> "translated translation units" and "instantiation units" instead of
> "library components". It's deliberately a bit fuzzy in order to allow
> various mechanisms. So the rule for objects is that if it's in a
> library, you'd better have an external reference to it somewhere in
> your program. If you want it, ask for it.


If it is intentional, I regret it.
The creator of a library component has a reason to put things
together in a translation unit. The maker of the "main program"
often does not know such details of a library component,
so why should he be asked to specify such details in the main program?
It makes the maintenance of such programs difficult in case
the implementation of a library changes.
If the maker of the library knows that objects can be eliminated,
without loss of functionality of other objects or function
he can put them in different translation units,
but how can he express that an object is required for other
functions or objects within the same translation unit other than
putting them together in a translation unit?
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      04-20-2010
On Apr 20, 11:20*am, "Fred Zwarts" <(E-Mail Removed)> wrote:
> "Pete Becker" <(E-Mail Removed)> wrote in message
>
> news(E-Mail Removed)
>
>
>
>
>
> > Fred Zwarts wrote:
> >> "Pete Becker" <(E-Mail Removed)> wrote in message
> >>news:(E-Mail Removed)
> >>> Fred Zwarts wrote:
> >>>> Interesting. What is the definition of a library component?
> >>> It's not defined. The old Unix rule was that each source file gets
> >>> compiled into an object file, and each object file is a single
> >>> entity: either it gets linked in in its entirety, or it doesn't get
> >>> linked in. Some compilers produce object files with finer
> >>> granularity: the linker can pull in only the parts that are
> >>> actually needed, and ignore other parts of the object file.

>
> >>>> Assuming that a library component is a translation unit:
> >>>> If a library component is linked in, should it be linked in
> >>>> completely, or is it also allowed to link in only those parts from
> >>>> a library component that satisfy external references?
> >>> Yes. <g>

>
> >> If the term "library component" is not defined,
> >> then the question could equally well be answered with No.

>
> >> But, as C++ talks in terms of translation units, I think that the
> >> linker
> >> should not eliminate parts of a unit, execpt if it can deduce that
> >> it has no effect on the execution of a program.

>
> > If that was the intention, the wording would have been about
> > "translated translation units" and "instantiation units" instead of
> > "library components". It's deliberately a bit fuzzy in order to allow
> > various mechanisms. So the rule for objects is that if it's in a
> > library, you'd better have an external reference to it somewhere in
> > your program. If you want it, ask for it.

>
> If it is intentional, I regret it.
> The creator of a library component has a reason to put things
> together in a translation unit. The maker of the "main program"
> often does not know such details of a library component,
> so why should he be asked to specify such details in the main program?
> It makes the maintenance of such programs difficult in case
> the implementation of a library changes.
> If the maker of the library knows that objects can be eliminated,
> without loss of functionality of other objects or function
> he can put them in different translation units,
> but how can he express that an object is required for other
> functions or objects within the same translation unit other than
> putting them together in a translation unit?


Translation units that are in libraries are linked into program only
if they resolve some unresolved external references.
The translation units that are not put into libraries but explicitly
linked into program are no subject of such selection and are always
linked into program. (Sounds terribly tautological but appears that it
is part that feels as ungranted to most people.)

What to do: Make a translation unit that externally references
something from every translation unit in libraries that you want to
link into program no matter what. Link such translation unit
explicitly and not as part of library.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
global variables initialization paresh C Programming 20 11-24-2008 09:18 PM
does value-initialization happen for global and local static object ? subramanian100in@yahoo.com, India C++ 1 04-21-2008 03:17 AM
global variable vs static member initialization order n.torrey.pines@gmail.com C++ 10 03-15-2007 02:21 PM
Global (static) Var in a library initialization question. Kyle C++ 6 11-10-2005 03:43 PM
Initialization of global variables Rahul Gandhi C Programming 3 02-02-2004 05:30 PM



Advertisments