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
我不知道使用该标志的其他后果是什么。
我正在使用 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
我不知道使用该标志的其他后果是什么。