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.

 
 
Milan Radovich
Guest
Posts: n/a
 
      04-18-2010

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?

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


A case where such an idiom is very usefull is described in Chapter 8.3 of
Andrei Alexandrescu's "Modern C++ Design".
 
Reply With Quote
 
 
 
 
Öö Tiib
Guest
Posts: n/a
 
      04-18-2010
On 18 apr, 22:04, Milan Radovich <using....@gmail.com> wrote:
> 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?


Yes. Standard does not describe "modules", "library" is used only in
context of standard libraries and "linker" is mentioned only in some
remarks. Standard does not describe how to make and how to interface
with custom libraries and what it means. There are no words about
shared and static custom libraries and so on. That is all up to
implementations.

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


Usually there are some relations between modules that you link
together. When you call (or at least make linker to believe that you
might call) something from translation unit where your bool bar is,
then that compilation unit gets linked in and bar gets initialized.
 
Reply With Quote
 
 
 
 
Milan Radovich
Guest
Posts: n/a
 
      04-18-2010
On Sun, 18 Apr 2010 12:57:43 -0700 (PDT), in comp.lang.c++ Öö Tiib <> wrote:

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

>
>Usually there are some relations between modules that you link
>together. When you call (or at least make linker to believe that you
>might call) something from translation unit where your bool bar is,
>then that compilation unit gets linked in and bar gets initialized.


The question is, how it could be done before static library is written.
That is, I want to write a.cc so that when libb.a is written and linked
with a.o, global variables from libb.a are linked in and initialized
when application is ran.

I don't want to change a.cc every time a new static library is added
to application.
 
Reply With Quote
 
Paul Bibbings
Guest
Posts: n/a
 
      04-18-2010
Milan Radovich <> writes:

> 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


Although this has no effect in relation to your current issue, you will
need to change the ordering here in the second invocation of g++. As
described in the documentation for gcc, "The linker handles an archive
file by scanning through it for members which define symbols that have
so far been referenced but not defined." What this means is, you have
to be correct as to ordering in supplying libraries and object files to
g++. As you have it above, you are passing g++ libb.a (-lb) *before* it
has seen your object file, a.o. Were you to require any library code
from libb.a in a.o (though you don't in the example given) this would
not be linked in because it would not "have so far been referenced but
not defined" at this point. This needs to be:

g++ -L. a.o -o a2 -lb

(As I have mentioned, the difference is not apparent in the example as
given, but will be an issue in more complete code).

> 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?


It is correct in the sense that the Standard puts little to no
requirements on static libraries; indeed it hardly mentions them at
all. In effect, it is an implementation detail. The difference you are
experinecing is not an inconsistency either, since you are applying two
different build models and the Standard, as mentioned, puts no
requirements on their `effect' being the same.

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


If I understand it correctly, you can view a static library (an
`archive') as a collection of the object files from which it is
composed. The linker will make the code from any one of the archived
object files available *only* if your program requires the code. By
`required', I mean that your user code references a symbol in that
archive file that is defined there. Currently, your code does not
reference any symbol in libb.a:b.o. The `pattern', then, is to ensure
that it does.

Note: this does not necessarily mean that your user code must reference
either bool foo() or const bool bar. It must, however, reference
/something/ in libb.a:b.o, or this won't be linked in. Indeed, why
should it? If you are not actually making any use of /any/ of the code
in libb.a:b.o, then what is the point of that code? Why would you want
const bool bar initialized and bool foo() called in doing so?

> A case where such an idiom is very usefull is described in Chapter 8.3 of
> Andrei Alexandrescu's "Modern C++ Design".


I am not familiar with this work and hence am not aware of how this
idiom is used here. Perhaps if you give a little more context about
what it is this idiom is intended to achieve, more concrete help can be
given.

Regards

Paul Bibbings
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      04-18-2010
On 18 apr, 23:07, Milan Radovich <using....@gmail.com> wrote:
> On Sun, 18 Apr 2010 12:57:43 -0700 (PDT), in comp.lang.c++ Tiib <oot...@hot.ee> wrote:
>
> >> 2) Is there is a pattern which forces linker to add such a code to an
> >> executable?

>
> >Usually there are some relations between modules that you link
> >together. When you call (or at least make linker to believe that you
> >might call) something from translation unit where your bool bar is,
> >then that compilation unit gets linked in and bar gets initialized.

>
> The question is, how it could be done before static library is written.
> That is, I want to write a.cc so that when libb.a is written and linked
> with a.o, global variables from libb.a are linked in and initialized
> when application is ran.
>
> I don't want to change a.cc every time a new static library is added
> to application.


I see. However what such singletons does? It is not actively related
to anything already written. It is just statically linked? What
benefits it provides to main module? Currently the uncertainty with
lots of threads causes issues with some idioms and patterns of
Alexandrescu, some of whose were probably meant to work well in single-
threaded environments.
 
Reply With Quote
 
Paul Bibbings
Guest
Posts: n/a
 
      04-18-2010
Milan Radovich <> writes:

> On Sun, 18 Apr 2010 12:57:43 -0700 (PDT), in comp.lang.c++ Öö Tiib <> wrote:
>
>>> 2) Is there is a pattern which forces linker to add such a code to an
>>> executable?

>>
>>Usually there are some relations between modules that you link
>>together. When you call (or at least make linker to believe that you
>>might call) something from translation unit where your bool bar is,
>>then that compilation unit gets linked in and bar gets initialized.

>
> The question is, how it could be done before static library is written.
> That is, I want to write a.cc so that when libb.a is written and linked
> with a.o, global variables from libb.a are linked in and initialized
> when application is ran.
>
> I don't want to change a.cc every time a new static library is added
> to application.


I am not sure that this quite makes sense to me. You appear to be
saying that you are writing a library that you are intending to link
into your program but that you don't want to have to change your program
code to actually make use of any of the library code you write.

As I have explained to some extent in a previous reply, as soon as your
user program code requires, in any direct or indirect way, code
incorporated into your library libb.a by the archived object file b.o,
then that object file will be linked in and the proper initialization
(of const bool bar, in this instance) will occur. If no such code is
required by your program, then this object code will not be linked in
and the initialization won't occur; but, of course, your not using it in
this second scenario, so why should it?

As an example, extending your original code:

// 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:07 Paul Bibbings@JIJOU
/cygdrive/d/CPPProjects/nano $rm a.o a2.exe b.o libb.a

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

Note that the added code does not directly make use of either bool
foo(), or const bool bar. It merely makes use of *a* symbol defined in
libb.a:b.o and that object file is linked in from the archive and
initialization of const bool bar occurs, calling bool foo().

To summarize, in the code as given *nothing* in a.cc makes use of any of
the code in b.cc which, in your second build process, is archived as
libb.a:b.o. Initialization of const bool bar does not occur *for this
reason*. Of course, in your actual implementation something /will/ make
use of some code in libb.a:b.o, or why are you building it? Further, it
will almost certainly use code in that object file that *requires* const
bool bar to be initialized, or else why is its initialization important
to you? In this event, then, this initialization will happen and it
will not require any further, specific `pattern' on your part other than
that you "use what your program requires."

Regards

Paul Bibbings

 
Reply With Quote
 
Balog Pal
Guest
Posts: n/a
 
      04-18-2010

"Milan Radovich" <>

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


> 1) Is it a correct behaviour according to a Standard?


IIRC the mandated behavior is that objects in a TU that appear at namespace
scope will be initialized (in proper order related to each other) sometimes
before any code in that TU gets executed.

That makes both your observed behaviors correct.

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


Sure, call function in that routine. Or use an implement-specific way to
force an extern/import symbol in one of your objects.


 
Reply With Quote
 
Milan Radovich
Guest
Posts: n/a
 
      04-19-2010
On Sun, 18 Apr 2010 21:56:14 +0100, Paul Bibbings <> wrote:

>I am not familiar with this work and hence am not aware of how this
>idiom is used here. Perhaps if you give a little more context about
>what it is this idiom is intended to achieve, more concrete help can be
>given.


Suppose there is a program which given a file performs some action
upon it, and different actions should be performed on different file types.
In order to make a program easily extensible, it has a hierarcy of file types,
where the program operates on abstract class File by calling it's function
Work. For each file type, new class is created. It inherits from File
and overrides File's private virtual function DoWork (called by Work).

In order to be able to extend the program easily, there is some (singleton)
FilesRegistry which given file's descriptor returns handler for this file.
When user wants to add handler for a new file type, he writes his handler
and registers it with FilesRegistry by calling it's static RegisterHandler
function.

Since we don't want file handler writer to modify the main program
(which may even be non-modifiable, like a framework), it is enough
for the user to define a global variable in his handler's file and initialize
it with return value of call to RegisterHandler function. Since global
variables should be initialized automatically, his handler would be
registered and everything work.

But...

If due to some compilation environment's quirks a static library should
be built from the new file handler and only then linked with the main
program, such a clean solution becomes impossible and the user is
forced to modify main code (by calling some function from his hander
or something like that).

This is undesirable, since modification of main source code may
introduce bugs, makes program less modular and complicates
creation of new file handers.

We want to avoid those problems.
 
Reply With Quote
 
Milan Radovich
Guest
Posts: n/a
 
      04-19-2010
On Sun, 18 Apr 2010 18:16:46 -0400, Pete Becker <> wrote:

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

>
>Depends on the tools. But in general, your code needs to reference
>whatever it is that you want linked in.


This is what I want to avoid in order to decouple those two pieces of
code, see an example in my reply to Paul Bibbings.
 
Reply With Quote
 
Milan Radovich
Guest
Posts: n/a
 
      04-19-2010
On Mon, 19 Apr 2010 00:27:47 +0200, "Balog Pal" <> wrote:

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

>
>Sure, call function in that routine. Or use an implement-specific way to
>force an extern/import symbol in one of your objects.


The code should be multiplatform and therefore very general, therefore
implementation-specific solutions are not suitable. Neither is function call,
as I just explained in reply to other posts in the thread.
 
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
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57