6

I'm currently facing an annoying issue with C++.

Actually, I don't even understand why I didn't face it for the past 20 years :(

In my current context, we heavily use c++ executables (mostly in Linux embedded systems) statically linked with our proprietary static libs. And we do use static libs for technical and optimization reasons.

Over the past years, indeed, I used to create shared libs though...

So I began to write some classes with static class members. Such as follow:

class Inner
{
public:
   Inner()
   {
     std::cout << "CTOR Inner" << std::endl;
   }
};

class A
{
static Inner _inner;

...
};

// in the .cpp

Inner A::_inner;

///////////////////////

Very basic use-case, isn't it ?

But in my unit-tests, linked with the lib, I can't see the std::cout statement in the console. Whereas, if I move my class Inner and A into the executable source-code...it works fine.

I'm sure it's a very basic issue and I realize I've never faced over the past years. Is it an issue related to the compilers ? Please note that I tested both cases on Windows and Linux (Debian, Gcc 4.9).

Any idea is welcome.

Z.

Zyend
  • 572
  • 1
  • 4
  • 24
  • Global variables are only guaranteed to be initialized before the first odr-use of an entity in its containing translation unit. If you never use the TU, you're not guaranteed to have globals initialized. – Kerrek SB Mar 01 '17 at 20:31
  • Ok. So I've to find a workaround to "properly" force their initialization...good. – Zyend Mar 01 '17 at 20:56
  • What is the actual use case of this? I find it pretty in line with expectation that the mere linking to a static library doesn't have side effects. If I don't use something, I shouldn't have to pay for it, that's a design principle behind C and C++. – zett42 Mar 01 '17 at 23:32

1 Answers1

9

You have to actually use A::_inner somehow or that part of code won't be included. Either that or use something else in that file. Linkers don't have to link in translation units that are never used, even if they'd have observable side effects.

How to force inclusion of "unused" object definitions in a library

Community
  • 1
  • 1
Edward Strange
  • 40,307
  • 7
  • 73
  • 125
  • You honor your nick, really! All my respect. – πάντα ῥεῖ Mar 01 '17 at 20:31
  • Thanks. Well...at first glance there's no "clean" solution to fix that issue. I'm not a fan of #pragma statements as it would make the whole thing dirty as possible... – Zyend Mar 01 '17 at 20:35
  • I defined some macros that basically allowed me to "DECLARE_FILE(x)" "DEFINE_FILE(x)" in the library header/cpp and then "USE_FILE(x)" in the main of my program. These would create a static int that was externed and then in the main it would be assigned to. This caused the translation unit to get included and thus the registration to happen. Something like that anyway, don't recall specifically what I did. – Edward Strange Mar 01 '17 at 20:38
  • Do you have a concrete example of a DECLAIRE_FILE and USE_FILE macros ? – Zyend Mar 01 '17 at 20:42