Primero entendamos la asignación del montón y la pila en el sistema operativo Windows con nuestras aplicaciones/DLL. Tradicionalmente, el sistema operativo y las bibliotecas en tiempo de ejecución vienen con una implementación del montón.
- Al comienzo de un proceso, el sistema operativo crea un montón predeterminado llamado Montón de proceso. El montón de procesos se usa para asignar bloques si no se usa ningún otro montón.
- Los tiempos de ejecución del lenguaje también pueden crear montones separados dentro de un proceso. (Por ejemplo, el tiempo de ejecución de C crea un montón propio).
- Además de estos montones dedicados, el programa de aplicación o una de las muchas bibliotecas de vínculos dinámicos (DLL) cargadas pueden crear y usar montones separados, llamados montones privados
- Este montón se encuentra encima del administrador de memoria virtual del sistema operativo en todos los sistemas de memoria virtual.
- Hablemos más sobre CRT y montones asociados:
- Asignador de tiempo de ejecución C/C++ (CRT):proporciona malloc() y free(), así como operadores nuevos y de eliminación.
- El CRT crea un montón extra para todas sus asignaciones (el identificador de este montón CRT se almacena internamente en la biblioteca CRT en una variable global llamada _crtheap) como parte de su inicialización.
- CRT crea su propio montón privado, que reside encima del montón de Windows.
- El montón de Windows es una capa delgada que rodea al asignador de tiempo de ejecución de Windows (NTDLL).
- El asignador de tiempo de ejecución de Windows interactúa con el asignador de memoria virtual, que reserva y asigna páginas utilizadas por el sistema operativo.
Su DLL y exe se vinculan a bibliotecas CRT estáticas de subprocesos múltiples. Cada DLL y exe que cree tiene su propio montón, es decir, _crtheap. Las asignaciones y desasignaciones tienen que ocurrir desde el montón respectivo. Que un DLL asignado dinámicamente no se puede desasignar del ejecutable y viceversa.
¿Lo que puedes hacer? Compile nuestro código en DLL y exe usando /MD o /MDd para usar la versión específica de subprocesos múltiples y DLL de la biblioteca en tiempo de ejecución. Por lo tanto, tanto DLL como exe están vinculados a la misma biblioteca de tiempo de ejecución de C y, por lo tanto, un _crtheap. Las asignaciones siempre se emparejan con desasignaciones dentro de un solo módulo.
Los archivos DLL/exe deberán vincularse a una implementación de bibliotecas de tiempo de ejecución de C.
En el caso de las bibliotecas C Windows Runtime, tiene la opción de especificar, si desea vincular a lo siguiente:
- Biblioteca de tiempo de ejecución C de subproceso único (la compatibilidad con bibliotecas de subproceso único se ha interrumpido ahora)
- DLL de subprocesos múltiples / DLL de depuración de subprocesos múltiples
- Bibliotecas estáticas de tiempo de ejecución.
- Algunos más (puede consultar el enlace)
Cada uno de ellos se referirá a un montón diferente, por lo que no se le permite pasar la dirección obtenida del montón de una biblioteca de tiempo de ejecución a otra.
Ahora, depende de a qué biblioteca de tiempo de ejecución de C se haya vinculado la DLL de la que está hablando. Supongamos que la DLL que está utilizando se ha vinculado a la biblioteca de tiempo de ejecución de C estática y el código de su aplicación (que contiene la función principal) se ha vinculado a la DLL de tiempo de ejecución de C multiproceso, entonces si pasa un puntero a la memoria asignada en el DLL a su programa principal e intente liberarlo allí o viceversa, puede conducir a un comportamiento indefinido. Entonces, la causa raíz básica son las bibliotecas de tiempo de ejecución de C. Por favor, selecciónelos cuidadosamente.
Encuentre más información sobre las bibliotecas de tiempo de ejecución de C admitidas aquí y aquí
Una cita de MSDN:
Precaución No mezcle versiones estáticas y dinámicas de las bibliotecas en tiempo de ejecución. Tener más de una copia de las bibliotecas en tiempo de ejecución en un proceso puede causar problemas, porque los datos estáticos en una copia no se comparten con la otra copia. El enlazador evita que se vincule con versiones estáticas y dinámicas dentro de un archivo .exe, pero aún puede terminar con dos (o más) copias de las bibliotecas en tiempo de ejecución. Por ejemplo, una biblioteca de vínculos dinámicos vinculada con las versiones estáticas (no DLL) de las bibliotecas en tiempo de ejecución puede causar problemas cuando se usa con un archivo .exe que se vinculó con la versión dinámica (DLL) de las bibliotecas en tiempo de ejecución. . (También debe evitar mezclar las versiones de depuración y no depuración de las bibliotecas en un solo proceso).