【发布时间】:2011-10-11 18:49:18
【问题描述】:
我有一个有趣的问题,我在互联网上的研究似乎没有解决这个问题。 我正在尝试使用 dlfcn.h 中的函数在我的 c++ 项目中动态加载库。问题是,当我尝试在运行时重新加载插件时(因为我对它们中的任何一个进行了更改),调用 dlclose() 时主程序崩溃(分段错误(核心转储))。 这是我重现错误的示例:
main.cpp:
#include <iostream>
#include <dlfcn.h>
#include <time.h>
#include "IPlugin.h"
int main( )
{
void * lib_handle;
char * error;
while( true )
{
std::cout << "Updating the .so" << std::endl;
lib_handle = dlopen( "./test1.so", RTLD_LAZY );
if ( ! lib_handle )
{
std::cerr << dlerror( ) << std::endl;
return 1;
}
create_t fn_create = ( create_t ) dlsym( lib_handle, "create" );
if ( ( error = dlerror( ) ) != NULL )
{
std::cerr << error << std::endl;
return 1;
}
IPlugin * ik = fn_create( );
ik->exec( );
destroy_t fn_destroy = ( destroy_t ) dlsym( lib_handle, "destroy" );
fn_destroy( ik );
std::cout << "Waiting 5 seconds before unloading..." << std::endl;
sleep( 5 );
dlclose( lib_handle );
}
return 0;
}
IPlugin.h:
class IPlugin
{
public:
IPlugin( ) { }
virtual ~IPlugin( ) { }
virtual void exec( ) = 0;
};
typedef IPlugin * ( * create_t )( );
typedef void ( * destroy_t )( IPlugin * );
Test1.h:
#include <iostream>
#include "IPlugin.h"
class Test1 : public IPlugin
{
public:
Test1( );
virtual ~Test1( );
void exec( );
};
Test1.cpp:
#include "Test1.h"
Test1::Test1( ) { }
Test1::~Test1( ) { }
void Test1::exec( )
{
std::cout << "void Test1::exec( )" << std::endl;
}
extern "C"
IPlugin * create( )
{
return new Test1( );
}
extern "C"
void destroy( IPlugin * plugin )
{
if( plugin != NULL )
{
delete plugin;
}
}
编译:
g++ main.cpp -o main -ldl
g++ -shared -fPIC Test1.cpp -o plugin/test1.so
例如,当我更改 Test1::exec 方法上的某些内容(更改要打印的字符串或注释行)并且在主程序休眠时,我将新的 test1.so 复制到主运行目录(cp )。如果我使用移动命令 (mv),则不会发生错误。使用 cp 或 mv 有什么区别?有没有办法解决这个问题或使用 cp 来解决这个问题?
我正在使用带有 g++ (GCC) 4.5.1 20100924 (Red Hat 4.5.1-4) 的 Fedora 14。
提前致谢。
【问题讨论】:
-
我想这是因为
RTLD_LAZY,试试RTLD_NOW。 -
优秀的问题组合。要是所有新成员都那么擅长写高质量的问题就好了!
-
我已经使用 RTLD_NOW 和提到的两个选项(RTLD_LAZY 和 RTLD_NOW)与 RTLD_GLOBAL 和 RTLD_LOCAL 进行了 ORed 测试。结果保持不变...
标签: c++ g++ dynamic-linking