Domanda

plugin1.cpp:

#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;
}

Costruisci ed esegui:

>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

Perché TestStatic :: ~ TestStatic chiamato a 'exit ()' ma non a 'dlclose ()'?

È stato utile?

Soluzione

Lo standard C ++ richiede che vengano chiamati oggetti globali quando un programma esce nell'ordine opposto di costruzione. La maggior parte delle implementazioni lo ha gestito chiamando la routine Atexit della libreria C per registrare i distruttori. Ciò è problematico perché lo standard C del 1999 richiede solo che il supporto di implementazione 32 funzioni registrate, sebbene la maggior parte delle implementazioni supporti molte altre. Ancora più importante, non si occupa affatto della capacità nella maggior parte delle implementazioni di rimuovere i DSO da un'immagine del programma in esecuzione chiamando DLClose prima della risoluzione del programma.

Questo problema è risolto nelle versioni successive di GCC tra cui la libreria standard C/C ++ e il linker. Fondamentalmente, i distruttori C ++ dovrebbero essere registrati usando __cxa_atexit funzione invece di atexit (3).

Per i dettagli tecnici completi su __cxa_atexit, vedere Specifica ABI Itanium C ++.


Non è chiaro dalla tua domanda quale versione di GCC, linker e libreria C standard stai utilizzando. Inoltre, il codice che hai fornito non si incontra Posix standard in quanto non ci sono RTDL_NOW o RTDL_LOCAL Macro definite. Sono RTLD_NOW e RTLD_LOCAL (vedere dlopen).

Se la tua libreria standard C non supporta __cxa_atexit, potrebbe essere necessario disabilitarlo specificando -fno-use-cxa-atexit Flag GCC:

-fuse-cxa-Atexit

Registra i distruttori per oggetti con durata di archiviazione statica con la funzione __cxa_ atexit piuttosto che la funzione atexit. Questa opzione è richiesta per la gestione completamente conforme agli standard di distruttori statici, ma funzionerà solo se la tua libreria C supporta __CXA_ATEXIT.

Ma ciò potrebbe causare un problema in cui i distruttori vengono chiamati in ordine diverso o per niente chiamati affatto. Quindi la soluzione migliore in caso di rotta __cxa_atexit Il supporto o nessun supporto non è quello di utilizzare oggetti statici con distruttori nelle librerie condivise.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top