Question

The answer here demonstrates that __attribute__((constructor)) is not called after static initialization, it is called in the declaration order.

Then, what is the purpose of it, if it is not guaranteed to be called when all data is initialized? We could as well have our ((constructor)) code in the Foo constructor.

What I'm looking for is a way to have, in a shared library, a code that will be executed after all static data is initialized and static constructors are called. I saw people recommending __attribute__((constructor)) as a replacement for DllMain; as we can see this is wrong, because some static data may still be not initialized.

Of course in single file (compilation unit) we could arrange statics. But in a typical program there's a lot of files. Is there a way to guarantee that ((constructor)) in one file will be definitely called after all other statics in a shared library are initialized?

If I put a file with static initialization (constructor, object, etc) to the end of the gcc command line:

g++ -shared -fPIC source1.o source2.o MyLastInitChance.o

are this file's static constructors guaranteed to be called last? I experimented and when I change order of source files, printfs' order is changed; but is it specified somewhere and guaranteed to be the same across compilation systems/computers?

For example, a quote:

At link time, the gcc driver places crtbegin.o immediately before all the relocatable files and crtend.o immediately after all the relocatable files. ©

From what I understand the quote above implies that order of .o files passed to the linker defines order of the static initialization. Am I correct?

Another interesting possible solution, maybe, is to write a GCC plugin that adjusts static initialization (e.g. adds code to .ctors section, etc). But this is just an idea that maybe someone can extend.

One more possible solution is presented here. In short, an external post-build tool can be used to reorder .ctors entries in the executable file (library). But I'm not an expert in ELF format; I wonder if this is possible and easy enough to tweak .so files in this way.

What I'm interested in is solving a particular problem, or proving that it is impossible to solve (at least why the solutions above would not work).

Was it helpful?

Solution

You might try using linker scripts for ld. You can read more about it here, but I guess what you are looking for is

.ctors : { *(SORT(.ctors)) MyLastInitChance.o(SORT(.ctors)) }
.dtors : { *(SORT(.dtors)) MyLastInitChance.o(SORT(.dtors)) }

in SECTIONS{...} block. That should rearrange .ctors sections so file provided will call it's constructors as the last one. Obviously more advanced solutions are also available if you find yorself in need for one;)

HINT: writing your own link-script is tedious. Use ld's --verbose option that prints out used link script and modify it. Then add your linking script using -T switch.

OTHER TIPS

the biggest advantage of attribute((constructor))__ is the priority associated with each block and specifically helps your case.

You have two block of codes which have data hazard (one set should be executed first). This cannot be achieved by single static block. Using one static block and one attribute((constructor))__ will not solve your problem because of confusion regarding the order.

The best way to deal with the problem is to have two attribute((constructor))__ with two different priorities. Move your existing static initialization block to higher priority (0) and the other code block to lower priority.

See this: http://gcc.gnu.org/ml/gcc-help/2011-05/msg00220.html and the answer http://gcc.gnu.org/ml/gcc-help/2011-05/msg00221.html

In particular quoting from the answer:

All objects with an init_priority attribute are constructed before any object with no init_priority attribute.

Note it is actually about __attribute__((init_priority)) and not about __attribute__((constructor)) but I believe they both actually use the same code in gcc, respectively in gnu linker. First just corresponds to C++ objects, i.e. calling their constructor/destructor, the latter is about marking specific functions as constructor or destructor.

IMHO, the __attribute__((constructor)) exists mainly because of C, not C++.

Can you implement a "construct on first use" pattern for this global?

e.g.

Magic& gMagic()
{
    static Magic magic;
    return magic;
}

It will get built after all regular static ctors, but before any regular code needs it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top