2009-06-09 11 views
6

¿Está bien registrar WSACleanup a través de la función atExit? Tenemos varias aplicaciones que pueden finalizar en diferentes puntos del código, por lo que nos gustaría evitar poner WSACleanup en todas partes a través del código. Curamente llamamos a WSAStartup/WSACleanup a través de DllMain ya que tenemos un dll que es utilizado por todas estas aplicaciones. Sin embargo, Microsoft recomienda estrictamente evitar el uso de WSAStartup/WSACleanup a través de DllMain, ya que esto puede causar interbloqueos. Podemos mover WSAStarup fuera de DllMain y llamarlo en un punto del código para todas las aplicaciones antes de que accedan a la biblioteca de sockets de Windows. Y, tan pronto como llamemos a WSAStartup, nos gustaría usar la función atExit para registrar una llamada a WSACleanup. ¿Alguien tiene alguna experiencia con este enfoque? ¡Gracias!WSACleanup y atExit

Respuesta

4

Si tiene una aplicación de subprocesos múltiples y algunos de los subprocesos aún están conectados, puede que las aplicaciones en el otro extremo no prefieran la forma en que termina la conexión. Por lo tanto, es preferible cerrar todas las comunicaciones de forma ordenada antes de que main() finalice, y cuando lo haya hecho, puede llamar a WSACleanup.

1

Bueno, creo que atExit no debe ser utilizado. Debe seguir el principio de RAII de envoltura de inicialización y destrucción de la biblioteca de socket en una clase.

+0

Si bien el estilo, esto no ayuda ni un ápice. Desde el punto de vista del proceso, el procesamiento atexit() ocurre al mismo tiempo que la ejecución de destructores globales. Cualquier problema que tenga al llamar a WSACleanup desde AtExit, es probable que aún tenga que llamarlo desde un dtor. – MSalters

2

Estoy de acuerdo en que el enfoque RAII es favorable.

Sin embargo, una palabra de advertencia: atExit mezclado con dlls y controladores se interrumpe en las ventanas. Desafortunadamente, esto también afecta a RAII ya que esto se implementa con manejadores de atExit en el tiempo de ejecución de C++.

El orden en que atexit manejadores se invocan en las ventanas:

  1. salida en algún lugar se llama o main() se sale del ámbito
  2. manipuladores atexit definidos en el proceso se llaman.
  3. todos los identificadores se destruyen.
  4. se llaman los controladores atexit definidos en dlls.

No importa si los manejadores de atexit en dlls están registrados antes que los manejadores en el proceso, los manejadores de proceso se llaman primero y los manejadores se destruyen antes de llamar a los controladores dll. Esto da como resultado excepciones win32, cuando se llama al código de limpieza ya que todos los identificadores propiedad de dlls ya no son válidos.

Este código de efectos tiene asas para hilos, mutex, archivos, sockets, etc. Si se asignan en un dll, entonces deben limpiarse antes de llamar a la salida o no funcionar.

Por cierto, no estoy en contra de la ventana, si estoy equivocado o alguien sabe alguna forma de evitar esto, me gustaría saber que esto me causa un dolor incalculable en la limpieza de la aplicación. Me imaginé que esto sería depurar el manejo de la salida en el tiempo de ejecución de C++, después de obtener excepciones win32 cuando las aplicaciones salgan.

Tuve que eliminar todas las llamadas para salir de mi código. Ahora me aseguré de que no hay datos estáticos en un dll controla un mango. Todos los controladores estáticos están controlados por objetos que se destruyen cuando el principal sale del alcance.

+1

No roto. Si descargó las DLL antes de los dtors globales del EXE, cualquier dtor de la aplicación fallaría al llamar a una función desde ese dtor.La configuración actual permite que el EXE dependa de las DLL, pero no al revés. Además, no debería abrir o cerrar identificadores en DLLMain, esa no es una regla nueva. El procesamiento AtExit forma parte de DLLMain, por lo que hereda esas reglas. Una solución rápida es utilizar punteros inteligentes para todos los recursos de DLL. Cuando la aplicación limpia su último puntero inteligente a un recurso DLL, la DLL sabrá que puede limpiar, y esto es antes de AtExit. – MSalters

+0

Gracias por la nota en DLLMain, no me di cuenta de esto. Su nota sobre el puntero inteligente: esto solo funcionará si se declara en main o below y no estático, ¿verdad? – iain

+0

Todavía no entiendo la forma correcta de hacerlo. ¿Qué pasa si tengo una DLL que proporciona una cierta funcionalidad? Una aplicación que carga el DLL e invoca ciertas funciones (que tienen acceso interno a la API de Winsock) necesita tener WSAStartup llamado al menos una vez. Puedo ajustar todas estas funciones en una clase y asegurarme de que WSAStartup se llame al menos una vez. La aplicación ahora puede salir en cualquier punto del tiempo y la única forma que veo de llamar a WSACleanup es a) a través de atExit o b) a través de un desctructor global. Por lo que entendí, ambos pueden causar problemas. ¿Cuál es la salida de esto? –

Cuestiones relacionadas