Wpadłem dziś na uszkodzenie sterty spowodowane różnymi ustawieniami CRT (MTd MDd) w mojej bibliotece dll i moim rzeczywistym projekcie. To, co znalazłem, jest dziwne, że aplikacja uległa awarii, gdy ustawiam destruktor w bibliotece dll tak, aby była wirtualna. Czy jest to łatwe wytłumaczenie? Rozumiem, że nie mogę zwolnić pamięci, która nie jest na mojej stercie, ale gdzie dokładnie jest różnica, kiedy definiuję destruktor jako nie-wirtualny.CRT wirtualny destruktor
jakiś kod, żeby zrobić to trochę jaśniej
DLL
#pragma once
class CTestClass
{
public:
_declspec(dllexport) CTestClass() {};
_declspec(dllexport) virtual ~CTestClass() {};
};
A mój projekt
int main(int argc, char* argv[])
{
CTestClass *foo = new CTestClass;
delete foo; // Crashes if the destructor is virtual but works if it's not
}
Czy masz ten sam problem, przenosząc declspec do * class * ("class _declspec (dllexport) CTestClass {...}") i usuwając declspecs dla poszczególnych członków? Po prostu ciekawy. I uwaga, kod wywołujący i biblioteka DLL powinny używać tego samego CRT (debugowania lub wydania), więc to coś do rozważenia. Nie jestem nawet pewien, czy obsługiwane są tryby mieszane (nie sądzę, że tak). – WhozCraig
Masz wiele kopii CRT w swoim procesie. Eksportujesz tylko metody klasy, a nie v-table. Próba wyjaśnienia, jak wszystkie te interakcje mają na celu zbombardowanie kodu, nie jest tak produktywna, jak się spodziewano.Eksportowanie klasy za pomocą metod wirtualnych wymaga wyeksportowania całej klasy, wstawienia __declspec (dllexport) obok słowa kluczowego * class *. I musisz upewnić się, że pojedynczy alokator jest używany do tworzenia i niszczenia obiektu. Bardzo trudne do zagwarantowania, chyba że kompilujesz z/MD konsekwentnie i używasz tej samej wersji kompilatora. Ujawnianie klas C++ poza granice modułów jest po prostu ryzykowne. –
Masz prawdopodobnie rację, nawet jeśli zrozumiem, dlaczego to nie działa, nie pomoże mi to zbytnio. Mimo to dziękuję za twoje myśli :) – Poisonbox