下面的代码演示了预期的行为(也可以说是直观的)。就像可执行文件中的静态对象在进入
问题是:这种运行时加载的库的行为是否有任何保证,或者它只是一个便利的偶然事件或幸运的实现细节?我们能否依赖于库中静态对象的构造函数被调用,还是必须使用标有
main()
之前被初始化一样,人们期望在动态加载库中的静态对象在 dlopen()
返回之前被初始化。问题是:这种运行时加载的库的行为是否有任何保证,或者它只是一个便利的偶然事件或幸运的实现细节?我们能否依赖于库中静态对象的构造函数被调用,还是必须使用标有
__attribute__((constructor))
的函数等替代方法来确保在 dlopen()
调用范围内实现某些所需的行为?// libtest.cpp
#include <iostream>
namespace
{
class Test
{
public:
Test() { std::cerr << "In Test()...\n"; }
~Test() { std::cerr << "In ~Test()...\n"; }
};
Test test; // when is this initialized?
}
// testso.cpp
#include <dlfcn.h>
#include <iostream>
int main( int ac, char* av[] )
{
if ( ac < 2 )
{
std::cerr << "Usage: " << av[0] << "library-name\n";
return 1;
}
std::cerr << "Before dlopen()...\n";
::dlerror();
void* _handle(::dlopen( av[1], RTLD_NOW ));
std::cerr << "After dlopen()...\n";
if ( !_handle )
{
std::cerr << "Error: " << ::dlerror() << ", exiting...\n";
return 2;
}
::dlclose( _handle );
std::cerr << "After dlclose()...\n";
return 0;
}
编译并运行(请注意在dlopen()
返回之前调用Test()
):
$ g++ -o libtest.so -shared -fPIC libtest.cpp
$ g++ -o testso -ldl testso.cpp
$ ./testso ./libtest.so
Before dlopen()...
In Test()...
After dlopen()...
In ~Test()...
After dlclose()...
$
.
__attribute__((constructor))
。它通常被认为是一种hack方法,而且不可移植。相反,使用一个导出的函数。只是提醒一下。 - Qix - MONICA WAS MISTREATED