Static lib global ctor issue

I posted a poorly phrased version of this question a while back. I've since done more research on it and am able to reproduce the error in a minimal compilable example.

For my program I'm using global objects to have themselves automatically added to a global vector (done in their ctor), so that this vector may be polled later to get a full list of these types of objects. This method worked fine in my early tests, but when a friend tries to compile my lib as a statically linked lib he ran into trouble, because apparently the ctors for the global objects were not being called.

Here is some code (as simple as I could make it) which reproduces the error.

There are 2 build targets:
- 'exe' (the executable which statically links to the lib)
- 'lib' (the library being statically linked to)

There are 3 source files:
- 'exe.cpp' (part of 'exe')
- 'lib.cpp' (part of 'lib')
- 'lib2.cpp' (part of 'lib')

And one header file:
- 'hdr.h' (included in both 'lib' and 'exe')

1
2
3
4
5
6
7
8
9
// hdr.h
class Foo
{
public:
    Foo();
    static int Get();

protected:
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// lib.cpp
#include "hdr.h"

//---------------------------------

static int& GetV()
{
    static int v = 0;
    return v;
}

Foo::Foo()
{
    ++GetV();
}

int Foo::Get()
{
    return GetV();
}

static Foo workingfine;      // this ctor works fine 

1
2
3
4
//lib2.cpp
#include "hdr.h"

static Foo      notworking;  // this ctor is not happening 

1
2
3
4
5
6
7
8
9
// exe.cpp
#include <iostream>
#include "hdr.h"

int main()
{
    std::cout << Foo::Get() << "\n";
    return 0;
}


Basically in this example, Foo objects increment a counter in their ctor, and that counter is printed by the exe, which should report the total number of Foo objects created.

Since the library has 2 Foo objects -- both global: one in lib.cpp and the other in lib2.cpp... it should be printing 2. However it's only printing 1 (the object in lib2.cpp apparently isn't being constructed).

Now... the kicker is... this only happens when the lib is statically linked. It works fine (prints 2) when dynamically linked, and when I put all source files in the same project (no separate lib).

I'm using GCC 4.3.2 with Code::Blocks on Ubuntu.
My friend is experiencing the same problem with VS2008 on ?WinXP? (I think)

Can anyone shed some light on this? I assume it's optimizing out the 'notworking' object because it's never directly used apart from its ctor -- but how can I stop it from doing that?

Any help greatly appreciated.


UPDATE:

Apparently (in GCC at least), it depends on whether or not anything in the source file is referenced. If I add a dummy function to lib2.cpp:

1
2
3
void dummy() { }  // add tilib2.cpp
//----
void dummy(); // add to hdr.h 


and call that function from main.cpp, then it works. Strange indeed!

EDIT AGAIN:

I suppose this means I can side-step the problem by making all these objects global in a different file (one that is always used), but that kind of sucks.

That's the solution I'll go with for now, for lack of anything better. If someone else has any other ideas, though, I'm really interested in hearing them.

EDIT ONE MORE TIME:

I came up with a "solution" which tricks the compiler into thinking the cpp file is used.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// hdr.h
class Foo
{
public:
    Foo();
    static int Get();

protected:
};

void dummy();       // empty body in lib2.cpp
static void never() // tricks compiler into thinking 'dummy' is used
{
    dummy();
}


This "successfully" side-steps the problem, but produces several compiler warnings ("function 'never' is never used"). This is the best workaround I can think of.

Still very interested in hearing other ideas, though, if anyone has any.
Last edited on
Topic archived. No new replies allowed.