Digamos que escribo una DLL en C++ y declaro un objeto global de una clase con un destructor no trivial. ¿Se llamará al destructor cuando se descargue la DLL?¿Qué sucede con las variables globales declaradas en una DLL?
Respuesta
En una DLL de Windows C++, todos los objetos globales (incluidos los miembros estáticos de las clases) se construirán justo antes de la llamada de DllMain con DLL_PROCESS_ATTACH, y se destruirán justo después de la llamada de DllMain con DLL_PROCESS_DETACH.
Ahora, debe tener en cuenta tres problemas:
0 - Por supuesto, los objetos no const globales son malos (pero ya saben que, por lo que evitará mentionning multithreading, cerraduras, dios-objetos, etc. .)
1 - El orden de construcción de objetos o diferentes unidades de compilación (es decir, archivos CPP) no está garantizado, por lo que no se puede esperar que el objeto A se construya antes B si los dos objetos se instancian en dos diferentes CPPs. Esto es importante si B depende de A. La solución es mover todos los objetos globales en el mismo archivo CPP, ya que dentro de la misma unidad de compilación, el orden de instanciación de los objetos será el orden de construcción (y el inverso de la orden de destrucción)
2 - Hay cosas que están prohibidas en el DllMain. Esas cosas probablemente también están prohibidas en los constructores. Así que evita bloquear algo. Ver excelente blog de Raymond Chen sobre el tema:
http://blogs.msdn.com/oldnewthing/archive/2004/01/27/63401.aspx
http://blogs.msdn.com/oldnewthing/archive/2004/01/28/63880.aspx
En este caso, la inicialización perezosa podría ser interesante: Las clases se mantienen en un estado "no inicializada" (punteros internos son NULL, booleanos son falsos, lo que sea) hasta que llame a uno de sus métodos, en cuyo punto se inicializarán. Si usa esos objetos dentro de la principal (o una de las funciones descendientes de la principal), estará bien, ya que se invocarán después de la ejecución de DllMain.
3 - Por supuesto, si algunos objetos globales en DLL A dependen de objetos globales en DLL B, debe tener mucho cuidado con el orden de carga DLL y, por lo tanto, dependencias.En este caso, los archivos DLL con dependencias circulares directas o indirectas le causarán una enorme cantidad de dolores de cabeza. La mejor solución es romper las dependencias circulares.
P.S .: Tenga en cuenta que en C++, el constructor puede lanzar, y usted no quiere una excepción en el medio de una carga de DLL, así que asegúrese de que sus objetos globales no utilizarán la excepción sin una muy buena razón. Como los destructores correctamente escritos no están autorizados a lanzar, la descarga de DLL debería estar bien en este caso.
Se debe ejecutar cuando finaliza la aplicación o cuando se descarga la DLL, lo que ocurra primero. Tenga en cuenta que esto es algo dependiente del tiempo de ejecución real contra el que está compilando.
Además, tenga cuidado con los destructores no triviales, ya que hay problemas de tiempo y pedidos. Su DLL puede estar descargada después de una DLL en la que confíe su destructor, que obviamente causaría problemas.
Cuando se llama a DllMain con el parámetro fdwReason = DLL_PROCESS_DETACH, significa que la DLL descarga la DLL. Este es el tiempo antes de que se llame al destructor de objetos globales/estáticos.
Esta página desde Microsoft entra en los detalles de inicialización DLL y destrucción de variables globales:
http://msdn.microsoft.com/en-us/library/988ye33t.aspx
Si desea ver el código real que se ejecuta cuando se enlaza un .dll, echar un vistazo a %ProgramFiles%\Visual Studio 8\vc\crt\src\dllcrt0.c
.
De la inspección, los destructores se llamarán a través de _cexit()
cuando la cuenta de referencia interna mantenida por el dll CRT llega a cero.
En Windows, los archivos de imagen binarios con extensión * .exe, * .dll están en PE format Dichos archivos tienen Entry Point. También se puede ver con la herramienta dumpbin como
dumpbin/cabeceras dllname.dll
Si utiliza el tiempo de ejecución de Microsoft C, entonces su punto de entrada será algo así como * * CRTStartup o DllMainCRTStartup
Tales funciones realizan la inicialización del tiempo de ejecución c y C++ y delegan la ejecución en (main, WinMain) o en DllMain respectivamente.
Si utiliza Microsoft de VC compilador continuación se puede ver en el código fuente de estas funciones en la suya directorio VC:
- crt0.c
- dllcrt0.c
proceso DllMainCRTStartup todas las cosas necesita iniciar/definir sus variables globales desde secciones .data en el escenario normal, cuando recupera la notificación DLL_PROCESS_DETACH durante la descarga dll. Por ejemplo:
- principal o WinMain de hilo de inicio de los rendimientos de los programas de control de flujo
- que explícitamente se llama a FreeLibrary y utilizar DLL-contador es cero
- 1. Exportación de variables globales desde DLL
- 2. Las variables globales inicializadas declaradas como "const" van al segmento de texto, mientras que las declaradas "Static" van al segmento de datos. ¿Por qué?
- 3. Variables globales con GO
- 4. Haciendo todas las variables globales
- 5. Imprimir todas las variables globales/variables locales?
- 6. Usando variables globales en backbone.js
- 7. ¿Las variables de instancia son las nuevas variables globales?
- 8. ¿En qué objeto se almacenan las variables globales de Javascript?
- 9. ¿Por qué las variables declaradas con "nuestro" son visibles en todos los archivos?
- 10. Confusión sobre las variables globales en python
- 11. variables globales en C++
- 12. Obtenga todas las variables de instancia declaradas en la clase
- 13. Obtención de todas las variables globales (javascript) en una página
- 14. ¿Por qué las variables globales se consideran malas prácticas?
- 15. variables globales en RequireJS
- 16. Variables globales en hadoop
- 17. ¿Por qué Lua se predetermina a las variables globales?
- 18. ASP.NET C# Las variables estáticas son globales?
- 19. Variables globales en R
- 20. ¿Por qué debería inicializar las variables de miembro en el orden en que están declaradas?
- 21. Hacer todas las variables globales, PHP
- 22. Variables globales y MPI
- 23. Inicializando variables globales en VBA
- 24. Dónde poner las variables globales en Rails 3
- 25. objetivo-c - variables globales
- 26. Greasemonkey y variables globales
- 27. variables globales compartidas en C
- 28. ¿Qué sucede con los identificadores en un programa?
- 29. Variables globales en C# .net
- 30. C++ de variables globales
Si uno proceso cambia un valor global, es el cambio observado en otro proceso? –
@ LB--: por lo general, no: cada proceso tiene su propia variable global * a menos que * usted los asigne en la memoria compartida o use un truco específico del sistema operativo para compartirlos entre todos los procesos que usen esa DLL (no lo hago). recuerde exactamente el truco en Windows, pero implicó # declaraciones de pragma, IIRC) – paercebal