8

I'm using __attribute__((init_priority(X))) in GCC like this:

Type1 __attribute__ ((init_priority (101))) name1 = value1;
Type2 __attribute__ ((init_priority (102))) name2 = value2;

in different source files. Let's say file1.cpp and file2.cpp. If I use this in same library it works as expected, name1 is initialized before name2 but if I use this in different libraries the order of initialization is not the expected one. I read on gcc documentation that this should work in different libraries as I expect, to define the order of initialization. Is there something wrong in the way I use this? Did you have same problem?

PS: refactoring is not a solution for this problem because I must port a very big project from Visual Studio.

Mircea Ispas
  • 20,260
  • 32
  • 123
  • 211
  • 3
    Thank the hopelessly broken language that is C++ for this nightmare. Only one of many problems with this terrible language. – Dan Moulding Jul 30 '10 at 14:51
  • 4
    Not the language is the problem here, the architecture is. It is a great programming language, but not all developers know how to use it. – Mircea Ispas Jul 30 '10 at 22:33
  • 3
    How is it not the fault of the language that the entry point of the program cannot be determined in any standard way? Something as fundamental as the starting point of a program should be easily identifiable in any decent language. – Dan Moulding Aug 02 '10 at 13:51
  • 2
    @Dan The entry point of the language is in fact `main` and all you have to do to avoid these initialization problems is avoid using global/static data in a way that has interactions between translation units. If you're creating enough global/static data that you have problems you should almost certainly rethink your design. – Mark B Aug 05 '10 at 19:32
  • 1
    If you're porting this code, how do you know that it actually always works in the correct order in VS? What if you upgrade your compiler version and it changes the order? I think in fact refactoring will make both ports better, and if done in steps should be manageable. – Mark B Aug 05 '10 at 19:35
  • @Mark - I *think* Dan's complaint is a little more general. Its not the entry point; rather its dependencies among objects. We can't express dependencies in a meaningful way. More correctly, we can't express dependencies at all. I understand a dependency graph and analysis could be a hard problem so it was left unanswered by the C/C++ committee. But why did the C/C++ committee refuse to give us a way to say "A depends upon B, and B depends upon C" so this chronic problem would go away? – jww Aug 12 '15 at 22:06

5 Answers5

11

The gcc documentation (gcc 4.4) says:

`init_priority (PRIORITY)'

In Standard C++, objects defined at namespace scope are guaranteed to be initialized in an order in strict accordance with that of their definitions in a given translation unit. No guarantee is made for initializations across translation units. However, GNU C++ allows users to control the order of initialization of objects defined at namespace scope with the `init_priority' attribute by specifying a relative PRIORITY, a constant integral expression currently bounded between 101 and 65535 inclusive. Lower numbers indicate a higher priority.

Nowhere is there any indication of how this applies with respect to libraries, especially shared libraries. I would expect static libraries (libxyz.a) to work the same as individual object files in this respect, since they are just a collection of object files, and the wording of the documentation suggests that it works across translation units (i.e. with different object files).

However, shared libraries are effectively executables in their own right --- within a given shared library the initialization is done in the specified order, but shared libraries are initialized as a whole in the order specified by the dynamic loader i.e. liba.so is loaded either before or after libb.so based on the ordering criteria of the loader, and the init_priority attribute cannot affect that ordering.

Anthony Williams
  • 66,628
  • 14
  • 133
  • 155
0

If your library is dynamic, i.e. .so and not .a, then ld will influence the order of things, and gcc can only control the order of init within the same ELF binary (which will be the sum of all the .o's and .a's).

Gianni
  • 4,300
  • 18
  • 24
0

If you want your things to be initialized in order, try building an init function with __attribute__((constructor (priority))).

Borealid
  • 95,191
  • 9
  • 106
  • 122
0

With GNU linker your shared libraries will be initialized one by one in the order of their dependencies, not in parallel. It means that if your binary depends on a shared library the shared library gets initialized before the dynamic initialization starts in your the binary.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
0

Are all the objects in question at the same namespace scope (I assume global)? I didn't see any guarantee in the GCC documentation that this was required to work across libraries (although it would make sense for the linker to do so).

In spite of your final note, I'm still going to suggest refactoring. If you have control of the code to use __attribute__ then you could be able to, at least, use a wrapper "instance" function that utilizes a static local to so the initialization. It would require some code change, but in general it should be able to be done in a semi-automatic sort of way. See http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.13.

Also note that if you fix/refactor the code, you don't run the risk of a compiler patch/update to your VS compiler suddenly breaking the code, possibly in non-obvious ways.

Mark B
  • 95,107
  • 10
  • 109
  • 188