Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux shared library init & deinit when also using c++ static initializer

I want to have automated calls to initialize and deinitialize my shared library.

In my shared library, I need some static initialization of C++ objects, among others because of use of third party code (e.g. UnitTest++). When my init function is executed, I need to be guaranted, that all static initialization of C++ objects (of all linked translation units) is done (and vice versa for deinit); so just the same conditions as the execution of main() can expect in a C++ program.

I've seen much informations about linux shared library init/deinit e.g. like:

  • Automatically executed functions when loading shared libraries
  • How to initialize a shared library on Linux
  • http://www.faqs.org/docs/Linux-HOWTO/Program-Library-HOWTO.html#INIT-AND-CLEANUP
But the provided solutions won't fit my needs. In both approaches (__attribute__((constructor)) and even -Wl,-init,<function name>) the init function seems to be called before static initialization of C++ objects is completely done.

I also played around with __attribute__ ((init_priority(…))) like:

class InitAndDeinit {
public:
    InitAndDeinit() {
        // Do some initialization
    }
    ~InitAndDeinit() {
        // Do some cleanup
    }
} initAndDeinit __attribute__((init_priority(65535)));

But that also won't place the calls to the desired point; even with __attribute__((constructor(65535))).

I'd tested with gcc 4.6.4, 4.7.3 and 4.8.1 (4.6.4 shows a slightly different behaviour regarding the sorting of __attribute__((constructor))).

Any suggestions?

My current workaround is to provide exported functions (lib_init() and lib_deinit()) which have to called manually by the application.

like image 770
Joe Avatar asked Oct 24 '13 21:10

Joe


1 Answers

Here's one possible solution.

Static objects in a TU are initialized in their order of definition. Append a definition of a static object of a special type T to the end of each source file. The constructor of T should increment a static zero-initialized member. As soon as the counter reaches the number of source files in the module (determined by a build script), call your lib_init().

lib_deinit() is called after the counter is decremented back to zero.

Each library should have its own T.

You should be able to modify your makefile such that you don't have to physically alter source files. For instance, instead of g++ -c foo.C use g++ -c myspecialstaticinitcode.C -o foo.C -include foo.C or something like that.

like image 69
n. 1.8e9-where's-my-share m. Avatar answered Sep 28 '22 05:09

n. 1.8e9-where's-my-share m.