Портится куча в C++ программе. Ситуация на 100% воспроизводится. Осталось только понять как добраться до причины ошибки. А именно кто и где портит кучу. При освобождении памяти (файл free.c) вызывается функция HeapFree:
retval = HeapFree(_crtheap, 0, pBlock);
и отладчик ругается на испорченную кучу.
Вопрос. Можно ли как-либо определить по каким адресам (диапазон адресов) происходит порча кучи?
А>и отладчик ругается на испорченную кучу. А>Вопрос. Можно ли как-либо определить по каким адресам (диапазон адресов) происходит порча кучи?
Поковыряй gflags по поводу включения отладки в куче для твоего процесса. В результате оно должно навернуться там, где ты портишь память. Приготовься к неожидонностям
Здравствуйте, Алексей., Вы писали:
А>Портится куча в C++ программе. Ситуация на 100% воспроизводится. Осталось только понять как добраться до причины ошибки. А именно кто и где портит кучу. При освобождении памяти (файл free.c) вызывается функция HeapFree:
А>
А>retval = HeapFree(_crtheap, 0, pBlock);
А>
А>и отладчик ругается на испорченную кучу.
А>Вопрос. Можно ли как-либо определить по каким адресам (диапазон адресов) происходит порча кучи?
HeapValidate Function
Validates the specified heap. The function scans all the memory blocks in the heap, and verifies that the heap control structures maintained by the heap manager are in a consistent state. You can also use the HeapValidate function to validate a single memory block within a specified heap, without checking the validity of the entire heap.
Пока попробовал запускать приложение с Application Verifier (Shift+Alt+F5) — неожиданность не заставила себя ждать
В operator new(size_t nSize):
_malloc_dbg вернула NULL — хотя памяти более чем полно
далее AfxGetModuleThreadState() вернула некий STATE в котором указатель на процедуру AfxNewHandler() которая при вызове генерирует исключение.
А>В operator new(size_t nSize): А>_malloc_dbg вернула NULL — хотя памяти более чем полно А>далее AfxGetModuleThreadState() вернула некий STATE в котором указатель на процедуру AfxNewHandler() которая при вызове генерирует исключение.
Если проблема повторяется — попробуйте полазить под дебагером и найти проблемный класс/кусок кода. Недавно у нас была таже проблема из-за разных настроек препроцессора в проектах один и тот же класс компилировался по разному, что очевидно, вызывало проблему.
Если проблема повторяется не часто, то можно попробовать purify, как Вам уже советовали.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>HeapValidate Function
Попробовал отловить ошибку при помощи HeapValidate. Почти получилось. В итоге runtime выдает:
Free Heap block 068228E0 modified at 068228FC after it was freed
Отладка по Data BreakPoint по адресу 068228FC не показывает никакого криминала:
1) выделяется память под объект
2) потом объект перед завершением программы удаляется, сначала в ячейку по адресу 068228FC записывается DDDDDDDD (объект удален), оптом FEEEFEEE (блок кучи освобожден), больше значение ячейки не меняется
3) далее происходят 2 вызова HeapValidate которые ничего не обнаруживают.
4) и наконец происходит еще один вызов HeapValidate который выдает приведенную выше ошибку.
Здравствуйте, szag, Вы писали:
S>Недавно у нас была таже проблема из-за разных настроек препроцессора в проектах один и тот же класс компилировался по разному, что очевидно, вызывало проблему.
Спасибо! Упоминание о проблемах препроцессора привело к экспериментированию с заголовочным файлом файлом в который были недавно добавлены новые переменные. Все оказалось просто — не инициализировались переменные в конструкторе.
Ошибка уже исправлена, но механизм самопроверки кучи (HeapValidate) не понятен.
PD>И что в этот момент по этому адресу находится ?
0xFEEEFEEE
PD>Между этими двумя вызовами кто-то портит кучу.
Это понятно, только не понятно каким образом. HeapValidate ругается на значение в памяти которое не менялось и которое уже дважды прошло проверку при помощи HeapValidate.
Здравствуйте, Алексей., Вы писали:
А>Это понятно, только не понятно каким образом. HeapValidate ругается на значение в памяти которое не менялось и которое уже дважды прошло проверку при помощи HeapValidate.
Дело не в том, что находится по этому адресу. Я рб этом спросил просто для того, чтобы узнать, изменилось там значение или нет.
Дело в том, что в куче есть управляющая информация. Вот, представь себе, тебе дали задачу самому менеджер кучи написать, то есть дан большой блок памяти, и на нем надо подраспределения делать. Про занятые участки говорить сейчас не будем, на них в конце концов указатели есть извне, а вот как быть со свободными ? Простейшее решение — связать их в список, при освобождении нового участка в этот список добавляем, при выделении — ищем в списке фрагмент подходящего размера, часть его отдаем, чать оставляем и т.д.
А список где хранить ? Да там же, в куче. Занятые участки сами по себе, а вот в свободных участках и хранится этот самый список (то есть в начале участка лежит управляющий блок). Его корректность можно и проверить.
Судя по всему, программа что-то в этих местах испортила.
Это лишь модель, там вроде как в действительности немного посложнее куча устроена. Но основная идея именно такая.