В Visual C ++ использование new[]
для выделения массива объектов, а затем delete
(не delete[]
) по умолчанию запускает неопределенное поведение следующего вида .
Для вызова деструкторов для всех объектов необходимо знать количество объектов, поэтому Visual C ++ вызывает ::operator new[]()
, чтобы выделить немного больший буфер, помещает количество элементов в начало, затем вызывает конструкторы и возвращает указатель на первый объект. Когда delete
выполнено, он уничтожает только первый объект, а затем передает неверный указатель в ::operator delete()
, который по умолчанию реализуется точно так же, как ::operator delete[]()
.
Если следующее
class Class {
public:
~Class() { Sleep( 0 );}
};
delete new Class[1];
компилируется в конфигурации выпуска и запускается под отладчиком, программа останавливается с точкой останова:
ntdll.dll!_DbgBreakPoint@0()
ntdll.dll!_RtlpBreakPointHeap@4() + 0x28 bytes
ntdll.dll!_RtlpValidateHeapEntry@12() + 0x113 bytes
ntdll.dll!_RtlDebugFreeHeap@12() + 0x97 bytes
ntdll.dll!_RtlFreeHeapSlowly@12() + 0x246cf bytes
ntdll.dll!_RtlFreeHeap@12() + 0x17646 bytes
sample.exe!free(void * pBlock=0x0003339c) Line 110 C
sample.exe!main() Line 48 C++
sample.exe!__tmainCRTStartup() Line 266 + 0x12 bytes C
kernel32.dll!_BaseProcessStart@4() + 0x23 bytes
, который выглядит как кучное повреждение - по крайней мере, это то, что я ожидал бы в этом случае.
Я пытался позвонить _heapchk()
до и после этой строки, и на удивление он возвращает _HEAPOK
оба раза. Я также включил обнаружение утечек памяти , и по окончании программы утечек не было.
Можно ли предположить, что куча полностью исправна, если _heapchk()
вернет _HEAPOK
?