Подтвердить что ты не робот

Visual Studio - как найти источник ошибок повреждения кучи

Интересно, есть ли хороший способ найти исходный код, вызывающий ошибку кучевого повреждения, учитывая адрес памяти данных, который был написан "вне" выделенного блока кучи в Visual Studio;

Выделенный (0008) элемент бесплатного списка 26F7F670 - неправильный размер (мертвый)

(Попытка записать некоторые заметки о том, как найти ошибки памяти)

Спасибо заранее!

4b9b3361

Ответ 1

Начните с установки windbg:

http://www.microsoft.com/whdc/Devtools/Debugging/default.mspx

Затем включите страницу, например:

gflags.exe –p /enable yourexecutable.exe /full

Это приведет к вставке страницы без записи после каждого распределения кучи.

После этого запуска исполняемый файл изнутри windbg, любая запись вне кучи теперь будет захвачена этим отладчиком. Для того, чтобы впоследствии перевернуть страницу, используйте это:

gflags.exe -p /disable yourexecutable.exe

Подробнее о том, как использовать страницу здесь.

Ответ 2

Возможно, вы можете попробовать Microsoft Application Verifier. Он решил аналогичную проблему для меня один раз, включив дополнительные проверки операций кучи. На мой взгляд, случайность искаженного адреса заключается в том, что куча может быть "тонко" повреждена, и проблема не появится, пока что-то не произойдет с кучей (например, массивное распределение/бесплатно).

Ответ 3

Возможно, слишком поздно, но если он скомпилирован с gcc и может работать на Linux, вы можете использовать valgrind, чтобы найти источник проблемы (я не помню флаги, я использовал его только один раз с большим успехом).

Ответ 5

Вы можете установить точку останова при записи на адрес памяти. Затем отладчик покажет вам код, который записывается в местоположение, но вам все равно нужно решить, какая из записей вызывает проблему.

Ответ 6

В окне 10 вы можете включить PageHeap в инструменте GFlags Tool, этот инструмент включен как часть Инструменты отладки для Windows.

Параметры кучи страницы в GFlags позволяют выбрать стандартную проверку кучи или полномасштабную проверку кучи. Помните, что полная проверка кучи использует полную страницу памяти для каждого распределения, что может вызвать нехватку системной памяти.

Чтобы включить кучу страниц в GFlags:

• Чтобы включить стандартную проверку кучи страниц, стандартная версия будет писать шаблон в конце каждого распределения кучи, а затем изучить шаблон, когда выделения будут освобождены.

Чтобы проверить, что все процессы используют:

gflags/r + hpa

gflags/k + hpa

для одного процесса:

gflags/p/enable ImageFileName

• Чтобы включить проверку полной кучи страниц для одного процесса, этот параметр помещает недоступную страницу в конце каждого распределения, чтобы программа немедленно останавливалась, если она пытается получить доступ к памяти за пределами выделения, это следует использовать только в одном процессе из-за большого потребления памяти.

gflags/i ImageFileName + hpa

gflags/p/enable ImageFileName/full

Две приведенные выше команды взаимозаменяемы.

Примечание. Все упомянутые выше параметры кучи страниц представляют собой системные настройки, хранящиеся в реестре (кроме/k), и остаются в силе до тех пор, пока вы их не измените. Параметр /k - это установка флага ядра для этого сеанса и будет потеряна, когда Windows выключится.

Другим полезным инструментом является Application Verifier, но это не является частью средств отладки для Windows, скорее он включен в пакет разработки программного обеспечения для Windows (SDK).

Ответ 7

Я предполагаю, что язык С++ является языком.

Если ошибка воспроизводима, а поврежденный адрес всегда один и тот же, вы можете поместить контрольную точку данных, чтобы остановить программу при записи по этому адресу.

Ответ 8

Убедитесь, что все библиотеки, на которые вы ссылаетесь, скомпилированы в той же версии CLR, что и приложение, которое вы используете, - все в Release или все в Debug.

При компиляции в Debug и Release вы фактически нацеливаете две разные версии библиотеки времени выполнения C. Эти версии совершенно разные, и они используют разные стратегии для выделения памяти, и они используют разные кучи. Но самое главное знать, что они НЕ совместимы друг с другом.

Библиотека времени исполнения Release C выделяет память как ожидалось, тогда как Debug добавит дополнительную информацию, такую ​​как блоки защиты для отслеживания переполнения буфера и местоположение, называемое функцией распределения, и, в свою очередь, выделяет больше памяти, чем Release.

Если вы связываете свое приложение с набором DLL, которые были созданы в Release and Debug, вы, скорее всего, попытаетесь удалить объект в одной среде CLR, которая была создана в другой. Это означает, что вы будете пытаться освободить большую или меньшую память, чем то, что было выделено объекту, и это может повредить кучу.

Вы должны создать свое приложение, а также приложить к библиотекам, которые построены в той же конфигурации, либо Release, либо Debug.

Эта проблема может возникать особенно в модулях, которые компилируются с использованием разных компиляторов.

Есть способ обойти, о котором я расскажу, но не рекомендую. Если по какой-то причине вам по-прежнему нужно создавать разные режимы, эта работа позволит выделить и освободить всю память из одной и той же общей кучи. API GetProcessHeap позволит вам получить доступ к общей куче во всех разных модулях. Используя HeapAlloc и HeapFree, вы можете выделить и освободить память в общей куче. Примечание. HeapAlloc и HeapFree должны заменить все вызовы на malloc и бесплатно в вашем приложении.