C++ 复制动态库时dlclose崩溃
我有一个有趣的问题,我在互联网上的研究似乎没有解决。 我试图用DLFCN .h函数在C++项目中动态加载库。问题是,当我试图在运行时重新加载插件时(因为我对任何插件都做了更改),调用dlclose()时主程序崩溃(分段错误(内核转储))。 下面是我重现错误的示例: main.cpp:C++ 复制动态库时dlclose崩溃,c++,g++,dynamic-linking,C++,G++,Dynamic Linking,我有一个有趣的问题,我在互联网上的研究似乎没有解决。 我试图用DLFCN .h函数在C++项目中动态加载库。问题是,当我试图在运行时重新加载插件时(因为我对任何插件都做了更改),调用dlclose()时主程序崩溃(分段错误(内核转储))。 下面是我重现错误的示例: main.cpp: #include <iostream> #include <dlfcn.h> #include <time.h> #include "IPlugin.h"
#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;
}
测试1.h:
#include <iostream>
#include "IPlugin.h"
class Test1 : public IPlugin
{
public:
Test1( );
virtual ~Test1( );
void exec( );
};
例如,当我在Test1::exec方法上更改某些内容(更改要打印的字符串或对行进行注释)并且在主程序睡眠时,我将新的Test1.so复制到主运行目录(cp)时,就会出现问题。如果使用move命令(mv),则不会发生错误。使用cp或mv有什么区别?有没有办法解决这个问题,或者使用cp解决这个问题
我将Fedora14与g++(GCC)4.5.12000924(Red Hat 4.5.1-4)一起使用
提前感谢。与此问题相关的
cp
和mv
之间的区别如下:
cp
打开目标文件并将新内容写入其中。因此,它将用新内容替换旧内容mv
不接触原始文件的内容。相反,它使目录入口指向新文件cp
,则内容现在已损坏,因此任何情况都可能发生(segfault很可能是一种结果)mv
,则打开的文件句柄仍然引用原始文件,该文件仍然存在于磁盘上,即使不再有该文件的目录项mv
替换共享对象,则应能够dlclose
旧对象和dlopen
新对象。然而,这并不是我已经做过或将要推荐的事情。试试这个:
extern "C"
void destroy( IPlugin * plugin )
{
if( plugin != NULL && dynamic_cast<Test1*>(plugin))
{
delete static_cast<Test1*>(plugin);
}
}
extern“C”
无效销毁(IPlugin*插件)
{
if(插件!=NULL&&dynamic_cast(插件))
{
删除静态_cast(插件);
}
}
我认为这是因为RTLD\u懒惰
,现在就试试RTLD\u
。很好的问题组合。要是所有的新成员都那么擅长写质量问题就好了!我已经用RTLD_NOW和前面提到的两个选项(RTLD_LAZY和RTLD_NOW)或RTLD_GLOBAL和RTLD_LOCAL对它进行了测试。结果保持不变…实现这一点的最佳方法通常是使用install
命令。这应该是注释,而不是答案。
#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
extern "C"
void destroy( IPlugin * plugin )
{
if( plugin != NULL && dynamic_cast<Test1*>(plugin))
{
delete static_cast<Test1*>(plugin);
}
}