2010-09-28 8 views
20

plugin1.cpp:dlclose() nicht die destructor der globalen Objekte nennen

#include <iostream> 

static class TestStatic { 
public: 
    TestStatic() { 
    std::cout << "TestStatic create" << std::endl; 
    } 
    ~TestStatic() { 
    std::cout << "TestStatic destroy" << std::endl; 
    } 
} test_static; 

host.cpp

#include <dlfcn.h> 
#include <iostream> 
int main(int argc,char *argv[]) { 
    void* handle = dlopen("./plugin1.so",RTLD_NOW | RTLD_LOCAL); 
    dlclose(handle); 
    return 0; 
} 

bauen und laufen:

>g++ -c plugin1.cpp -o plugin1.o -fPIC 
>g++ -shared plugin.o -o plugin1.so 
>g++ host.cpp -o host -ldl 
>./host 
>TestStatic create 
>Segmentation fault 

warum TestStatic :: ~ TestStatic bei 'exit()' aufgerufen aber nicht bei 'dclclose()'?

+0

Gute Frage: +1. – Chubsdad

+2

Ist das hilfreich? http://forum.soft32.com/linux2/dlclose-causing-segmentierung-fault-exit-main-ftopict10002.html – Chubsdad

+0

Option-fno-use-cxa-atexit zum Kompilieren plugin.cpp Problem zu lösen – AndryBlack

Antwort

15

Der C++ - Standard erfordert, dass Destruktoren für globale Objekte aufgerufen werden, wenn ein Programm in der umgekehrten Reihenfolge der Konstruktion ausgeführt wird. Die meisten Implementierungen haben dies durch Aufrufen der C-Bibliothek atexit-Routine zum Registrieren der Destruktoren gehandhabt. Dies ist problematisch, da der C-Standard von 1999 nur erfordert, dass die Implementierung 32 registrierte Funktionen unterstützt, obwohl die meisten Implementierungen viel mehr unterstützen. Noch wichtiger ist, dass es in den meisten Implementierungen überhaupt nicht möglich ist, DSOs aus einem laufenden Programmabbild zu entfernen, indem dclose vor dem Beenden des Programms aufgerufen wird.

Dieses Problem wird in späteren Versionen von GCC behoben, einschließlich C/C++ - Standardbibliothek und Linker. Grundsätzlich sollten C++ - Destruktoren mit der Funktion __cxa_atexit anstelle von atexit (3) registriert werden.

Die vollständigen technischen Details zu __cxa_atexit finden Sie unter Itanium C++ ABI specification.


Es ist nicht klar aus Ihrer Frage, welche Version der GCC, Linker und Standard-C-Bibliothek Sie verwenden. Außerdem erfüllt der von Ihnen angegebene Code nicht den Standard POSIX, da keine RTDL_NOW oder RTDL_LOCAL Makros definiert sind. Sie sind RTLD_NOW und RTLD_LOCAL (siehe dlopen).

Wenn Ihr C-Standardbibliothek nicht __cxa_atexit unterstützen, können Sie es deaktivieren müssen durch die Angabe -fno-use-cxa-atexit gcc Flagge:

-fuse-cxa-atexit

Register Destruktoren für Objekte mit statischen Speicher Dauer mit der __cxa_ atexit Funktion anstelle der atexit Funktion. Diese Option ist erforderlich für vollständige standardkonforme Behandlung von statischen Destruktoren, funktioniert aber nur , wenn Ihre C-Bibliothek __cxa_atexit unterstützt.

Aber das könnte zu einem Problem führen, wo Destruktoren in anderer Reihenfolge oder gar nicht aufgerufen werden. Daher ist die beste Lösung im Fall von gebrochenen __cxa_atexit Unterstützung oder keine Unterstützung ist nicht statische Objekte mit Destruktoren in Ihren gemeinsamen Bibliotheken zu verwenden.

Verwandte Themen