Я столкнулся с коррупцией кучи сегодня, вызванной различными настройками ЭЛТ (MTd MDd) в моей DLL и моим фактическим проектом. Что я нашел странным, так это то, что приложение только разбилось, когда я установил деструктор в DLL, чтобы быть виртуальным. Есть ли легкое объяснение этому? Я понимаю, что я не могу освободить память, которая не на моей куче, но где именно разница, когда я определяю деструктор как не виртуальный.Виртуальный деструктор CRT
Некоторые код только, чтобы сделать это немного понятнее
DLL,
#pragma once
class CTestClass
{
public:
_declspec(dllexport) CTestClass() {};
_declspec(dllexport) virtual ~CTestClass() {};
};
И мой проект
int main(int argc, char* argv[])
{
CTestClass *foo = new CTestClass;
delete foo; // Crashes if the destructor is virtual but works if it's not
}
Кроме того, есть ли у вас такая же проблема, перемещая declspec в класс * ('class _declspec (dllexport) CTestClass {...}') и удаляйте pers-member declspecs? Просто любопытно. И обратите внимание, что вызывающий код и DLL должны использовать один и тот же CRT (отладка или выпуск), поэтому нужно что-то рассмотреть. Я даже не уверен, что поддерживаются смешанные режимы (я не думаю, что это так). – WhozCraig
У вас есть несколько копий ЭЛТ в вашем процессе. И вы экспортируете только методы класса, а не v-таблицу. Попытка выяснить, как все это взаимодействует, чтобы бомбить ваш код, не настолько продуктивна, как ожидается.Для экспорта класса с помощью виртуальных методов необходимо экспортировать весь класс, поместите __declspec (dllexport) рядом с ключевым словом * class *. И вы должны убедиться, что для создания и уничтожения объекта используется один распределитель. Очень сложно гарантировать, если вы не будете строить с/MD последовательно и использовать ту же самую версию компилятора. Выявление классов C++ по границам модулей является рискованным. –
Вы правы, даже если я выясню, почему это не работает, это не поможет мне слишком много. Спасибо, в любом случае, за ваши мысли :) – Poisonbox