dlclose() 静态析构函数 运行 在不同的时间,如果函数是虚拟的

dlclose() static destructors run at different times if function is virtual

我正在使用 dlopen() 和 dlclose() 加载和卸载模块。该模块包含一些需要在调用 dlclose() 时销毁的静态数据。但是我发现在某些情况下 dlclose() 不会调用析构函数 - 相反它们只会在 main() 退出时调用。

我已经将我的代码归结为这个。我有一个 class,其中包含在 class 中定义的虚函数 getType(),引用静态数据。我还有一个 StaticDestructionChecker 对象,它只在调用静态构造函数和析构函数时打印。最后我有一个 main() 函数,它通过 dlopen() 加载其他所有内容,通过 dlclose() 关闭它并在 main() 完成时打印:

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;

主要内容:

#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;
}

运行 所有这些原样导致静态数据在 main 终止后被破坏,即输出是:

Constructing static data
end of main
Destructing static data

问题出在 getType() 中的 virtual/static 组合。如果我将 getType() 更改为非虚拟的,或者如果我删除了 "static int t",析构函数将在预期时被调用,即输出为:

Constructing static data
Destructing static data
end of main

有没有办法在保持 virtual/static 代码的同时获得正确的销毁顺序?仅供参考,这是一种自定义 RTTI 系统的简化版本,其中 getType() 是通过 DECLARE_xxx 宏自动生成的,所以我不想将实现移到 cpp 文件中,因为需要那里也有第二个宏调用。 我在 Ubuntu 12 上使用 GCC 4.8。 谢谢

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

如果你使用 gold 链接器而不是在链接时传递 --no-gnu-unique 标志 module1.so 修复了问题:

]$ 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

我不知道使用该标志的其他后果是什么。