У меня есть интересная проблема, которая, кажется, не решена моими исследованиями в Интернете.
Я пытаюсь загружать библиотеки динамически в моем проекте c ++ с функциями из dlfcn.h. Проблема в том, что когда я пытаюсь перезагрузить плагины во время работы (потому что я внес изменения в любой из них), происходит сбой основной программы (ошибка сегментации (сбрасывается ядро)) при вызове 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?
Я использую Fedora 14 с g ++ (GCC) 4.5.1 20100924 (Red Hat 4.5.1-4).
Заранее спасибо.