Question

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

construire et exécuter:

>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

pourquoi TestStatic :: ~ TestStatic appelé à 'exit ()' mais pas 'dlclose ()?

Était-ce utile?

La solution

  

La norme C ++ exige que Destructeurs être appelé à des objets globaux lorsqu'un programme se termine dans l'ordre inverse de la construction. La plupart des implémentations ont traité en appelant la routine bibliothèque C atexit pour enregistrer les Destructeurs. Cette situation est problématique parce que la norme C 1999 exige seulement que le soutien de la mise en œuvre 32 fonctions enregistrées, bien que la plupart des implémentations prennent en charge beaucoup plus. Plus important encore, il ne traite pas du tout avec la capacité dans la plupart des mises en œuvre pour éliminer les DSO d'une image de programme en cours d'exécution en appelant dlclose avant la fin du programme.

Ce problème est résolu dans les versions ultérieures de GCC, y compris C / C ++ bibliothèque standard et éditeur de liens. Fondamentalement, les destructeurs de C doivent être enregistrées en utilisant la fonction de __cxa_atexit au lieu de atexit (3).

Pour les détails techniques sur __cxa_atexit, consultez C ++ ABI Itanium spécification .


Il ne ressort pas de votre question quelle version de gcc, éditeur de liens et de la bibliothèque standard C que vous utilisez. De plus, le code que vous avez fourni ne répond pas à la norme Posix car il n'y a pas de macros RTDL_NOW ou RTDL_LOCAL définies . Ils sont RTLD_NOW et RTLD_LOCAL (voir dlopen ).

Si votre bibliothèque standard C ne supporte pas __cxa_atexit, vous devrez peut-être désactiver en spécifiant le drapeau gcc -fno-use-cxa-atexit:

  

-fuse-CXA-atexit

     

Inscrivez-vous pour les objets avec Destructeurs stockage statique   durée avec le atexit __cxa_   fonction plutôt que la atexit   une fonction. Cette option est nécessaire pour   manipulation entièrement conforme aux normes de   Destructeurs statiques, mais ne fonctionnent   si votre bibliothèque C supports   __cxa_atexit.

Mais cela pourrait conduire à un problème où destructeurs sont appelés dans un ordre différent ou non appelé du tout. Donc, la meilleure solution en cas de support cassé __cxa_atexit ou aucun soutien est de ne pas utiliser des objets statiques avec dans vos bibliothèques Destructeurs partagées.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top