DlClose no llama a los destructores de la biblioteca, Dlopen llamó solo una vez -- 12.10 campo con g++ campo con glibc campo con ld campo con dynamic-linking camp askubuntu Relacionados El problema

dlclose does not call library destructors, dlopen called just once


1
vote

problema

Español

Considere el siguiente código para una biblioteca cargada dinámica construida con G ++ - 4.7 en Linux, ABCDEFGHIJKLMNABCDEFGHIJKLMN2 y vinculado con -rdynamic Opción:

  typedef std::vector< void* > cbRegister_t;  struct Wrapper {     cbRegister_t instance;     Wrapper() : instance() { HDebugLog("Wrapper CTOR!");}     ~Wrapper() { HDebugLog("Wrapper DESTRUCTOR!"); } }; inline cbRegister_t& getLibraryUnregisterMap() {     static Wrapper unregisterLibraryMap;     HDebugLog("getLibraryUnregisterMap: we have " <<unregisterLibraryMap.instance.size() << " elements. the address of the map is " << &unregisterLibraryMap.instance);     return unregisterLibraryMap.instance; }  void registerLibrary(void* p) {   auto& map = getLibraryUnregisterMap();   map.push_back(p); }  void unregisterLibrary() {   auto& map = getLibraryUnregisterMap(); }  void __attribute__ ((constructor)) library_init() {   static SomeData cbContainer;   HDebugLog("Library constructor: address of static cbContainer is: " << &cbContainer );   registerLibrary( &cbContainer); }  void __attribute__ ((destructor)) library_fini() { unregisterLibrary(); }   

Este código se carga bien de un cliente con ABCDEFGHIJKLMNABCDEFGHIJKLMN5 y ABCDEFGHIJKLMNABCDEFGHIJKLMNABCDEFGHIJKLMN6 BLAG. El constructor de la biblioteca se llama. El problema ocurre cuando llamo dlclose en el asa. Da cero de estado, lo que significa que fue exitoso. Pero el destructor de la biblioteca library_fini no se llama. ABCDEFGHIJKLMNABCDEFGHIJKLMN9 se llama en un solo lugar para que el recuento de referencia no sea un problema, sino que para estar absolutamente seguro de que realmente no hay dpkg-query - show - showformat = '$ {Package} n' 0 intenté hacer el ABCDEFGHIJKLMNABCDEFGHIJKLMN11 Varias veces:

  dpkg-query - show - showformat = '$ {Package}  n' 2  

Todos esos registros de depuración muestran que cada vez que llamo dpkg-query - show - showformat = '$ {Package} n' 3 El resultado de estado es cero. ¡ÉXITO!

La última afirmación, que no falla, confirma que la biblioteca ya no está residente. Pero en este punto dpkg-query - show - showformat = '$ {Package} n' 4 no ha sido llamado todavía!

Este comportamiento es definitivamente un error, ya sea en GCC o ABCDEFGHIJKLMNABCDEFGHIJKLMN15 (o lo que sea que esté usando Linux / Ubuntu para cargar dinámicamente las bibliotecas en estos días). Este comportamiento claramente no es lo que dice la norma, porque se debe garantizar que los destructores de la biblioteca se ejecuten si el recuento de referencia es cero antes de que DlClose devuelve . Los destructores de la biblioteca se ejecutan después del ABCDEFGHIJKLMNABCDEFGHIJKLMN16 , lo que hace que el destructor de la biblioteca sea completamente inútil, ya que no puede realizar ninguna finalización de los datos

Original en ingles

consider the following code for a dynamic loaded library built with g++-4.7 on linux, -fPIC and linked with -rdynamic option:

typedef std::vector< void* > cbRegister_t;  struct Wrapper {     cbRegister_t instance;     Wrapper() : instance() { HDebugLog("Wrapper CTOR!");}     ~Wrapper() { HDebugLog("Wrapper DESTRUCTOR!"); } }; inline cbRegister_t& getLibraryUnregisterMap() {     static Wrapper unregisterLibraryMap;     HDebugLog("getLibraryUnregisterMap: we have " <<unregisterLibraryMap.instance.size() << " elements. the address of the map is " << &unregisterLibraryMap.instance);     return unregisterLibraryMap.instance; }  void registerLibrary(void* p) {   auto& map = getLibraryUnregisterMap();   map.push_back(p); }  void unregisterLibrary() {   auto& map = getLibraryUnregisterMap(); }  void __attribute__ ((constructor)) library_init() {   static SomeData cbContainer;   HDebugLog("Library constructor: address of static cbContainer is: " << &cbContainer );   registerLibrary( &cbContainer); }  void __attribute__ ((destructor)) library_fini() { unregisterLibrary(); } 

This code loads fine from a client with dlopen and the RTLD_NOW flag. The library constructor is called. The problem happens when i call dlclose on the handle. It gives status zero, meaning that it was successful. But the library destructor library_fini is not called. dlopen is called on a single place so the reference count should not be a problem, but in order to be absolutely sure that there are really no references dangling i tried doing the dlclose several times:

int result = dlclose(handle); HDebugLog("Library::dynamicLibraryClose: closing library: " << libraryPath); HDebugLog("Library::dynamicLibraryClose: dlclose 1 failed with error: " << result << " => " ); result = dlclose(handle); HDebugLog("Library::dynamicLibraryClose: dlclose 2 failed with error: " << result << " => " ); result = dlclose(handle); HDebugLog("Library::dynamicLibraryClose: dlclose 3 failed with error: " << result << " => " ); result = dlclose(handle); HDebugLog("Library::dynamicLibraryClose: dlclose 4 failed with error: " << result << " => " ); result = dlclose(handle); HDebugLog("Library::dynamicLibraryClose: dlclose 5 failed with error: " << result << " => " ); result = dlclose(handle); HDebugLog("Library::dynamicLibraryClose: dlclose 6 failed with error: " << result << " => "); result = dlclose(handle); HDebugLog("Library::dynamicLibraryClose: dlclose 7 failed with error: " << result << " => "); result = dlclose(handle); HDebugLog("Library::dynamicLibraryClose: dlclose 8 failed with error: " << result << " => " ); HAssertMsg( !libraryPath.empty(), "library path is not set"); HAssertMsg( 0 == dlopen(libraryPath.c_str(), RTLD_NOLOAD) , "library is still loaded"); 

All those debug logs show that each time i call dlclose the status result is zero. Success!

The last assertion, which doesn't fail, confirms that the library is not resident anymore . But at this point library_fini has not been called yet!

This behavior is definitely a bug, either on gcc or ld.so (or whatever is using linux/ubuntu to dynamically load libraries these days). This behavior clearly is not what the standard says, because library destructors should be guaranteed to be run if the reference count is zero before dlclose returns. library destructors happen to be run after the Wrapper.instance is destroyed, which renders the library destructor completely useless, as is not able to do any finalization of the data

              
 
 

Lista de respuestas

2
 
vote
vote
La mejor respuesta
 

Esto funciona con GLIBC 2.17, GCC 4.8.0 o ICC 13.1 o ICC 12.1:

ABCDEFGHIJKLMNABCDEFGHIJKLMN14

 / * test.c * / #incluir #incluir  int __attribute __ ((constructor)) x_init (void) {     pone ("init () funciona");     return 0; }  int __attribute __ ((destructor)) x_fini (void) {     pone ("Fini () funciona");     return 0; } 

contra:

  last -d 5  

También probado con GLIBC 2.10, GLIBC 2.12. Y todo last -d 6 banderas.

Editar:
Usando un sistema real de Ubuntu (GCC (Ubuntu / Linaro 4.7.2-2UBUNTU1) 4.7.2), Biblioteca GNU C (Ubuntu Eglibc 2.15-0ubuntu20), debo decir que el código anterior también funciona allí. Así que tal vez después de todo, no se trata del compilador y / o Glibc.

 

This works with glibc 2.17, gcc 4.8.0 or icc 13.1 or icc 12.1:

icc -std=c99 -nostdlib -shared test.c -o /tmp/test

 /* test.c */ #include  #include   int __attribute__((constructor)) x_init(void) {     puts("init() works");     return 0; }  int __attribute__((destructor)) x_fini(void) {     puts("fini() works");     return 0; } 

against:

#include <dlfcn.h>  int main(void) {     void *foo = dlopen("/tmp/test", RTLD_LAZY);      if (dlclose(foo) < 0) {         return 1;     }     return 0; } 

Also tested with glibc 2.10, glibc 2.12. And all RTLD_* flags.

Edit:
Using an actual Ubuntu system (gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2), GNU C Library (Ubuntu EGLIBC 2.15-0ubuntu20), I must say that above code works there too. So maybe after all it's not about the compiler and/or glibc.

 
 
         
         

Relacionados problema

1  ¿Por qué puedo compilar contra libclang-3.5.so y no contra libclang.so?  ( Why can i compile against libclang 3 5 so and not against libclang so ) 
Estoy tratando de compilar un archivo de origen de C, que debe estar vinculado contra una biblioteca dinámica que instalé a través de apt-get (libclang.so)....

8  ¿Cómo ejecuto un juego con una extensión ?x86  ( How do i run a game with a x86 extension ) 
¿Puede alguien ayudarme a ejecutar el juego CS portátil, solía tocar esto todo el tiempo en Windows? Es gratis y el enlace de descarga es aquí , El enlace de...

29  ¿Dónde busca Ubuntu a las bibliotecas compartidas?  ( Where does ubuntu look for shared libraries ) 
Cuando ejecuto un proceso que vincula a una biblioteca compartida en Tiempo de ejecución (vinculado cuando se inicia el proceso, no vinculado más tarde con d...

0  Libjpeg no encontrado  ( Libjpeg not found ) 
Tengo un programa binario para correr en Ubuntu. Tiene dependencia de objetos compartidos. PMVS es el nombre del programa $ ldd pmvs linux-vdso....

0  ¿Cómo copiar las bibliotecas se construye un programa en vínculo dinámicamente?  ( How to copy libraries a dynamically linked program is built against ) 
Recientemente, he estado haciendo compilación de software y distribuiéndolo. La última vez que lo hice, lo hice construyendo mi programa y ejecutando LDD para...

0  LIBPNG-DEV está instalado; El programa no vincula  ( Libpng dev is installed program doesnt link ) 
Quiero compilar Farbfeld Program Suite. Yo ejecuto ABCDEFGHIJKLMNABCDEFGHIJKLMN3 . ERROR: cc -s -lpng -o png2ff png2ff.o util.o png2ff.o: In function `m...

0  Construir con clang para mayores lanzamientos de Ubuntu  ( Build with clang for older ubuntu releases ) 
Entonces, el problema comenzó como actualizé últimamente mi Ubuntu Vivid (15.04). Ahora ABCDEFGHIJKLMNABCDEFGHIJKLMN0 depende de ./my_app: /usr/lib/x86_6...

8  ¿Por qué hay un lugar en mi directorio de inicio?  ( Why is there a steampath in my home directory ) 
En el terminal, veo un enlace roto que se llama .steampath , no quité /home/user/.steam/sdk32/steam , pero se ha ido. ¿Por qué es el ABCDEFGHIJKLMNABCD...

20  ¿Qué están haciendo los programas de Linux?  ( What are dlls doing in linux programs ) 
Juegos que se hicieron con Unity3D para Linux Contiene ABCDEFGHIJKLMNABCDEFGHIJKLMN1 Archivos en su carpeta de datos ABCDEFGHIJKLMNABCDEFGHIJKLMN2 . que ...

3  Cómo restablecer LD_PRELOAD  ( How to reset ld preload ) 
He realizado el siguiente comando para configurar la ruta para LD_PRELOAD. Pero es el camino equivocado. export LD_PRELOAD=/home/ ¿Alguien sabe cuál es...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos