Oggi mi sono imbattuto in un danneggiamento dell'heap causato da diverse impostazioni CRT (MTd MDd) nella mia DLL e nel mio progetto attuale. Quello che ho trovato strano è che l'applicazione si è bloccata solo quando ho impostato il distruttore nella dll come virtuale. C'è una spiegazione facile per quello? Capisco che non posso liberare memoria che non è nel mio heap, ma dove esattamente è la differenza quando definisco il distruttore come non virtuale.Distruttore virtuale CRT
Alcuni codice solo per renderlo un po 'più chiaro
La DLL
#pragma once
class CTestClass
{
public:
_declspec(dllexport) CTestClass() {};
_declspec(dllexport) virtual ~CTestClass() {};
};
e il mio progetto
int main(int argc, char* argv[])
{
CTestClass *foo = new CTestClass;
delete foo; // Crashes if the destructor is virtual but works if it's not
}
Inoltre, hai lo stesso problema spostando declspec in * class * ('classe _declspec (dllexport) CTestClass {...}') e rimuovi i declspec per membro? Solo curioso. E nota, il codice chiamante e la DLL dovrebbero usare lo stesso CRT (debug o release), quindi questo è qualcosa da considerare. Non sono nemmeno sicuro che le modalità miste siano supportate (non penso che lo siano). – WhozCraig
Nel tuo processo hai più copie del CRT. Ed esporti solo i metodi di classe, non la v-table. Cercare di capire come tutto questo interagisce per bombardare il tuo codice non è così produttivo, è previsto.Esportare una classe con metodi virtuali richiede di esportare l'intera classe, mettere __declspec (dllexport) accanto alla parola chiave * class *. E devi assicurarti che un singolo allocatore sia usato per creare e distruggere l'oggetto. Molto difficile da garantire se non si costruisce con/MD in modo coerente e si utilizza la stessa esatta versione del compilatore. Esporre le classi C++ oltre i limiti del modulo è solo rischioso. –
Hai ragione, anche se capisco perché non funziona, non mi aiuterà troppo. Grazie comunque per i tuoi pensieri :) – Poisonbox