Per prima cosa comprendiamo l'allocazione dell'heap e lo stack sul sistema operativo Windows rispetto alle nostre applicazioni/DLL. Tradizionalmente, il sistema operativo e le librerie di runtime vengono fornite con un'implementazione dell'heap.
- All'inizio di un processo, il sistema operativo crea un heap predefinito chiamato Process heap. L'heap del processo viene utilizzato per l'allocazione dei blocchi se non viene utilizzato nessun altro heap.
- Anche i tempi di esecuzione del linguaggio possono creare heap separati all'interno di un processo. (Ad esempio, il runtime C crea un proprio heap.)
- Oltre a questi heap dedicati, il programma applicativo o una delle numerose librerie a collegamento dinamico (DLL) caricate possono creare e utilizzare heap separati, chiamati heap privati
- Questi heap si trovano in cima al Virtual Memory Manager del sistema operativo in tutti i sistemi di memoria virtuale.
- Discutiamo di più su CRT e sugli heap associati:
- Allocatore run-time C/C++ (CRT):fornisce malloc() e free() oltre agli operatori new e delete.
- Il CRT crea un tale heap aggiuntivo per tutte le sue allocazioni (l'handle di questo heap CRT è memorizzato internamente nella libreria CRT in una variabile globale chiamata _crtheap) come parte della sua inizializzazione.
- CRT crea il proprio heap privato, che risiede sopra l'heap di Windows.
- L'heap di Windows è uno strato sottile che circonda l'allocatore di runtime di Windows (NTDLL).
- L'allocatore di runtime di Windows interagisce con l'allocatore di memoria virtuale, che riserva e salva le pagine utilizzate dal sistema operativo.
Il collegamento DLL ed exe alle librerie CRT statiche multithread. Ogni DLL ed exe che crei ha un proprio heap, ad esempio _crtheap. Le allocazioni e deallocazioni devono avvenire dal rispettivo heap. Che una DLL allocata dinamicamente non possa essere deallocata dall'eseguibile e viceversa.
Cosa puoi fare? Compila il nostro codice in DLL ed exe utilizzando /MD o /MDd per utilizzare la versione specifica per multithread e specifica per DLL della libreria di runtime. Quindi sia DLL che exe sono collegati alla stessa libreria di runtime C e quindi a un _crtheap. Le allocazioni sono sempre abbinate a deallocazioni all'interno di un singolo modulo.
DLL / ex dovranno essere collegati a un'implementazione delle librerie di runtime C.
In caso di librerie C Windows Runtime, hai la possibilità di specificare, se desideri collegarti a quanto segue:
- Libreria di runtime C a thread singolo (il supporto per le librerie a thread singolo è stato ora interrotto)
- DLL multi-thread / DLL di debug multi-thread
- Librerie di runtime statiche.
- Pochi altri (puoi controllare il link)
Ciascuno di essi farà riferimento a un heap diverso, quindi non è consentito passare l'indirizzo ottenuto dall'heap di una libreria di runtime all'altro.
Ora, dipende da quale libreria di runtime C è stata collegata la DLL di cui stai parlando. Supponiamo che la DLL che stai utilizzando sia stata collegata alla libreria di runtime C statica e che il codice dell'applicazione (contenente la funzione principale) sia collegato alla DLL di runtime C multi-thread, quindi se passi un puntatore alla memoria allocata nel DLL al tuo programma principale e prova a liberarlo lì o viceversa, può portare a un comportamento indefinito. Quindi, la causa principale di base sono le librerie di runtime C. Si prega di sceglierli con cura.
Puoi trovare maggiori informazioni sulle librerie di runtime C supportate qui e qui
Una citazione da MSDN:
Attenzione Non mischiare versioni statiche e dinamiche delle librerie di runtime. Avere più di una copia delle librerie di runtime in un processo può causare problemi, poiché i dati statici in una copia non vengono condivisi con l'altra copia. Il linker ti impedisce di collegarti con entrambe le versioni statiche e dinamiche all'interno di un file .exe, ma puoi comunque finire con due (o più) copie delle librerie di runtime. Ad esempio, una libreria a collegamento dinamico collegata alle versioni statiche (non DLL) delle librerie di runtime può causare problemi se utilizzata con un file .exe collegato alla versione dinamica (DLL) delle librerie di runtime . (Dovresti anche evitare di mescolare le versioni di debug e non di debug delle librerie in un unico processo.)