Pageheap не всегда обнаруживает повреждение кучи именно в тот момент, когда оно происходит.
Pageheap вставляет недопустимую страницу сразу после распределения. Поэтому всякий раз, когда вы выходите за пределы выделенного блока, вы получаете AV. Но возможны и другие случаи. Одним из примеров является запись непосредственно перед выделенным блоком, который повреждает структуру данных заголовка блока кучи. Заголовок блока кучи является действительной доступной для записи памятью (скорее всего, на той же странице, что и выделенный блок). Рассмотрим следующий пример:
#include <stdlib.h>
int
main()
{
void* block = malloc(100);
int* intPtr = (int*)block;
*(intPtr-1) = 0x12345; // no crash
free(block); // crash
return 0;
}
Так что писать какой-то мусор непосредственно перед тем, как выделенный блок проходит нормально. С включенным параметром Pageheap пример разрывается внутри вызова free()
. Вот стек вызовов:
verifier.dll!_VerifierStopMessage@40() + 0x206 bytes
verifier.dll!_AVrfpDphReportCorruptedBlock@16() + 0x239 bytes
verifier.dll!_AVrfpDphCheckNormalHeapBlock@16() + 0x11a bytes
verifier.dll!_AVrfpDphNormalHeapFree@16() + 0x22 bytes
verifier.dll!_AVrfDebugPageHeapFree@12() + 0xe3 bytes
ntdll.dll!_RtlDebugFreeHeap@12() + 0x2f bytes
ntdll.dll!@RtlpFreeHeap@16() + 0x36919 bytes
ntdll.dll!_RtlFreeHeap@12() + 0x722 bytes
heapripper.exe!free(void * pBlock=0x0603bf98) Line 110 C
> heapripper.exe!main() Line 11 + 0x9 bytes C++
heapripper.exe!__tmainCRTStartup() Line 266 + 0x12 bytes C
kernel32.dll!@BaseThreadInitThunk@12() + 0xe bytes
ntdll.dll!___RtlUserThreadStart@8() + 0x27 bytes
ntdll.dll!__RtlUserThreadStart@8() + 0x1b bytes
Pageheap включает строгие проверки согласованности кучи, но проверки не срабатывают до тех пор, пока не будет вызван какой-либо другой API кучи. Подпрограммы проверки видны в стеке. (Без Pageheap приложение, вероятно, просто AV в реализации кучи попыталось бы использовать недопустимый указатель.)
Таким образом, Pageheap не дает вам 100% гарантии обнаружения повреждения именно в тот момент, когда оно происходит. Вам нужны такие инструменты, как Purify или Valgrind, которые отслеживают каждый доступ к памяти.
Не поймите меня неправильно, я думаю, что Pageheap по-прежнему очень полезен. Он вызывает гораздо меньшее снижение производительности по сравнению с упомянутыми Purify и Valgrind, поэтому позволяет запускать гораздо более сложные сценарии.
person
glagolig
schedule
07.09.2013