我有一个有趣的问题,似乎在我的互联网研究中尚未解决。 我试图从dlfcn.h函数中动态加载我的C++项目中的库。问题是,当我尝试在运行时重新加载插件(因为我对它们中的任何一个进行了更改),当调用dlclose()时,主程序崩溃(分段错误(核心转储))。 这是我的例子能重现错误: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
当例如我改变在测试1东西:: exec方法(改变串要被打印或评论的直线)时发生该问题并且在主程序睡我复制新的test1.so到主要运行目录(cp)。如果我使用move命令(mv),则不会发生错误。使用cp或mv的区别是什么?有什么办法可以解决这个问题,或者用cp来解决这个问题吗?
我用g ++(GCC)4.5.1 20100924(Red Hat 4.5.1-4)使用Fedora 14。
在此先感谢。
我想这是因为'RTLD_LAZY',试着用'RTLD_NOW'。 – Dani
优秀的问题组合。如果只有所有新成员都擅长编写质量问题! – sehe
我已经用RTLD_NOW和上面提到的两个选项(RTLD_LAZY和RTLD_NOW)对RTLD_GLOBAL和RTLD_LOCAL进行了OR操作,然后对它进行了测试。结果保持不变... – carlosms