0

I'm using dlopen() and dlclose() to load and unload a module. The module contains some static data which needs to be destructed when dlclose() is called. However I'm finding that under certain circumstances dlclose() does not call the destructors - instead they are only called when main() exits.

I've boiled my code down to this. I have a class which contains a virtual function getType() defined inside the class, making reference to static data. I also have a StaticDestructionChecker object which just prints when the static constructors and destructors are being called. Finally I have a main() function that loads everything else via dlopen(), closes it via dlclose() and prints when main() is finished:

module1.h

#ifndef MODULE1_H
#define MODULE1_H 

class MyClass
{
public:
    MyClass();
    virtual ~MyClass();

    virtual int& getType() const
    {       
        static int t(123); 
        return t;   
    }
};
#endif // MODULE1_H

module1.cpp

#include <stdio.h>
#include "module1.h"

MyClass::MyClass()
{
}

MyClass::~MyClass()
{
}

class StaticDestructionChecker
{
public:
    StaticDestructionChecker()
    {
        printf("Constructing static data\n");
    }
    ~StaticDestructionChecker()
    {
        printf("Destructing static data\n");
    }
};

StaticDestructionChecker checker;

main:

#include <dlfcn.h>
#include <stdio.h>
int main(int argc, char *argv[]) 
{
    void* handle = dlopen("module1.so", RTLD_NOW);
    if (!handle) printf("dlopen error: %s\n", dlerror());
    dlclose(handle);
    printf("end of main\n");
    return 0;
}

Running all this as-is causes the static data to be destructed after main terminates, ie the output is:

Constructing static data
end of main
Destructing static data

The problem is with the virtual/static combo in getType(). If I change getType() to be non-virtual OR if I remove the "static int t", the destructors get called when expected, ie output is:

Constructing static data
Destructing static data
end of main

Is there a way to get the correct destruction order while still keeping the virtual/static code? FYI this is a simplified version of a sort of custom RTTI system, where getType() is automatically generated via a DECLARE_xxx macro, so I don't want to move the implementation into the cpp file because there would need to be a second macro call in there too. I am using GCC 4.8 on Ubuntu 12. Thanks

gimmeamilk
  • 2,016
  • 5
  • 24
  • 36

1 Answers1

0

See dlclose() doesn't work with factory function & complex static in function?

If you use gold linker than passing --no-gnu-unique flag when linking module1.so fixes the problem:

]$ g++ -o module1.so -shared -fPIC -Wl,--no-gnu-unique module1.cpp
]$ g++ main.cpp -ldl
]$ LD_LIBRARY_PATH=. ./a.out
Constructing static data
Destructing static data
end of main

I don't know what are other consequences of using that flag.

Community
  • 1
  • 1
danadam
  • 3,350
  • 20
  • 18