Pregunta

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

construir y ejecutar:

>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

¿Por qué teststatic :: ~ teststatic llamado a 'Exit ()' pero no en 'dlClose ()'?

¿Fue útil?

Solución

El estándar C ++ requiere que los destructores se llamen a objetos globales cuando un programa sale en el orden opuesto de construcción. La mayoría de las implementaciones han manejado esto llamando a la rutina de Atexit de la Biblioteca C para registrar los destructores. Esto es problemático porque el estándar C de 1999 solo requiere que la implementación admite 32 funciones registradas, aunque la mayoría de las implementaciones admiten muchas más. Más importante, no se ocupa de la capacidad de la mayoría de las implementaciones para eliminar las DSO de una imagen del programa en ejecución llamando a DLClose antes de la terminación del programa.

Este problema se aborda en versiones posteriores de GCC, incluida la biblioteca estándar C/C ++ y el enlazador. Básicamente, los destructores de C ++ deben registrarse utilizando __cxa_atexit función en lugar de atexit (3).

Para obtener los detalles técnicos completos en __cxa_atexit, ver Especificación de itanium C ++ ABI.


No está claro a partir de su pregunta qué versión de la Biblioteca GCC, Linker y Standard C está utilizando. Además, el código que ha proporcionado no cumple Posix estándar ya que no hay RTDL_NOW o RTDL_LOCAL Macros definidas. Están RTLD_NOW y RTLD_LOCAL (ver dlopen).

Si su biblioteca estándar C no admite __cxa_atexit, es posible que deba deshabilitarlo especificando -fno-use-cxa-atexit Bandera GCC:

-Sefuse-cxa-atexit

Registre los destructores para objetos con duración de almacenamiento estático con la función __cxa_ atexit en lugar de la función Atexit. Esta opción es necesaria para el manejo totalmente compatible con los destructores estáticos, pero solo funcionará si su biblioteca C admite __cxa_atexit.

Pero eso podría resultar en un problema en el que los destructores se llaman en diferentes orden o no se llaman en absoluto. Entonces la mejor solución en caso de roto __cxa_atexit El soporte o ningún soporte no es usar objetos estáticos con destructores en sus bibliotecas compartidas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top