7.2.1. Поиск повреждений кучи

7.2.1. Поиск повреждений кучи

Когда память распределяется в куче, функциям управления памятью необходимо место для хранения информации о распределениях. Таким местом является сама куча; это значит, что куча состоит из чередующихся областей памяти, которые используются программами и самим функциями управления памятью. Это означает, что переполнения или недополнение буфера может фактически повредить структуру данных, которую отслеживают функции управления памятью. В такой ситуации есть много шансов, что сами функции управления памятью, в конце концов, приведут к сбою программы.

Если вы установили переменную окружения MALLOC_CHECK_, выбирается другой, несколько более медленный набор функций управления памятью. Этот набор более устойчив к ошибкам и может обнаруживать ситуации, когда free() вызывается более одного раза для одного и того же указателя, а также когда происходят однобайтные переполнения буфера. Если MALLOC_CHECK_ установлена в 0, функции управления памятью просто более устойчивы к ошибкам, но не выдают никаких предупреждений. Если MALLOC_CHECK_ установлена в 1, функции управления памятью выводят предупреждения о стандартных ошибках при замеченной проблеме. Если MALLOC_CHECK_ установлена в 2, функции управления памятью вызывают abort(), когда замечают проблемы.

Установка MALLOC_CHECK_ в 0 может оказаться полезной, если вам мешает найти ошибку в памяти другая ошибка, которую в этот момент исправить нет возможности; эта установка позволяет работать с другими средствами отслеживания ошибок памяти.

Установка MALLOC_CHECK_ в 1 полезна в случае, когда никаких проблем не видно, поэтому определенные уведомления могут помочь.

Установка MALLOC_CHECK_ в 2 наиболее полезна при работе в отладчике, поскольку при возникновении ошибки он позволяет выполнить обратную трассировку вплоть до функций управления памятью. В результате вы максимально приблизитесь к месту возникновения ошибки.

$ MALLOC_CHECK_=1 ./broken

malloc: using debugging hooks

malloc: используются отладочные функции

1: 12345

free(): invalid pointer 0x80ac008!

free(): недопустимый указатель 0x80ac008!

2: 12345678

3: 12345678

4: 12345

5: 12345

6: 12345

7: 12345

$ MALLOC_CHECK_=2 gdb ./broken

...

(gdb) run

Starting program: /usr/src/lad/code/broken

Запуск программы: /usr/src/lad/code/broken

1: 12345

Program received signal SIGABRT, Aborted.

Программа получила сигнал SIGABRT, прервана.

0x00 с 64 с 32 in _dl_sysinfo_int80() from/lib/ld-linux.so.2

(gdb) where

#0 0x00c64c32 in _dl_sysinfo_int80() from /lib/ld-linux.so.2

#1 0x00322969 in raise() from /lib/tls/libc.so.6

#2 0x00324322 in abort() from /lib/tls/libc.so.6

#3 0x0036d9af in free_check() from /lib/tls/libc.so.6

#4 0x0036afa5 in free() from /lib/tls/libc.so.6

#5 0x0804842b in broken() at broken.c:17

#6 0x08048520 in main() at broken.с:47

Другой способ заставить glibc проверить кучу на непротиворечивость — воспользоваться функцией mcheck():

typedef void(*mcheck Callback)(enummcheck_status status);

void mcheck(mcheck Callback cb) ;

В случае вызова функции mcheck(), функция malloc() размещает известные последовательности байтов перед и после возвращенной области памяти, чтобы можно было обнаружить переполнение или недогрузку буфера, free() ищет эти сигнатуры и, если они были повреждены, вызывает функцию, указанную аргументом cb. Если cb равен NULL, выполняется выход. Запуск программы, связанной с mcheck(), в gdb может показать, какие именно области памяти были повреждены, если только они явно освобождаются с помощью free(). Однако метод mcheck() не может точно определить место ошибки; лишь программист может вычислить это, основываясь на понимании логики работы программы.

Компоновка нашей тестовой программы с mcheck дает следующие результаты:

$ gcc -ggdb -о broken broken.с -lmcheck

$ ./broken

1: 12345

memory clobbered past end of allocated block

память разрушена после конца распределенного блока

Вследствие того, что mcheck всего лишь выдает сообщения об ошибках и завершает работу, найти ошибку невозможно. Для точного обнаружения ошибки потребуется запустить программу внутри gdb и заставить mcheck вызывать abort() при обнаружении ошибки. Можно просто вызвать mcheck() внутри gdb или поместить mcheck(1) в первой строке вашей программы (веред вызовом malloc()). (Следует отметить, что mcheck() можно вызвать в gdb без необходимости компоновки программы с библиотекой mcheck.)

$ rm -f broken; make broken

$ gdb broken

...

(gdb) break main

Breakpoint 1 at 0x80483f4: file broken.c, line 14.

Точка прерывания 1 по адресу 0x80483f4: файл broken, с, строка 14.

(gdb) command 1

Type commands for when Breakpoint 1 is hit, one per line.

End with a line saying just "end".

Наберите команды, которые выполнятся при достижении точки прерывания 1, по одной в строке.

Завершите строкой, содержащей только "end".

> call mcheck(&abort)

> continue

> end (gdb) run

Starting program: /usr/src/lad/code/broken

Запуск программы: /usr/src/lad/code/broken

Breakpoint 1, main () at broken.с: 14

47 return broken();

$1 = 0

1: 12345

Program received signal SIGABRT, Aborted.

Программа получила сигнал SIGABRT, прервана.

0x00e12c32 in _dl_sysinfo_int80() from /lib/ld-linux.so.2

(gdb) where

#00x00el2c32 in _dl_sysinfo_int80() from /lib/ld-linux.so.2

#1 0x0072c969 in raise() from /lib/tls/libc.so.6

#2 0x0072e322 in abort() from /lib/tls/libc.so.6

#3 0x007792c4 in freehook() from /lib/tls/libc.so.6

#4 0x00774fa5 in free() from /lib/tls/libc.so.6

#5 0x0804842b in broken() at broken.c:17

#6 0x08048520 in main() at broken.с:47

Важной частью этого кода является обнаруженная ошибка в строке 17 файла broken.с. Видно, что ошибка была обнаружена во время первого вызова free(), который указал на наличие проблемы в области памяти dyn. (freehook() представляет собой ловушку, с помощью которой mcheck выполняет проверки.)

Библиотека mcheck не может помочь в обнаружении переполнения или недогрузки буфера в локальных или глобальных переменных, а только в областях памяти, распределенных с помощью malloc().

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Яндекс. Поиск – быстрый поиск документов

Из книги Microsoft Office автора Леонтьев Виталий Петрович

Яндекс. Поиск – быстрый поиск документов Документы, как известно, имеют премерзкое свойство накапливаться. И чем больше документов, тем труднее в их залежах найти нужный. Электронные документы здесь не слишком отличаются от бумажных. Проблема места для хранения, правда,


Поиск

Из книги Реестр Windows автора Климов Александр

Поиск Классический видЧтобы использовать классический вид поиска файлов без анимированного персонажа, то присвойте строковому параметру Use Search Asst значение no в разделе HKCUSoftwareMicrosoftWindowsCurrentVersionExplorerCabinetStateОчистка истории раннее вводимых словЕсли вы часто пользуетесь


Поиск

Из книги 33 лучшие программы для ноутбука [Популярный самоучитель] автора Пташинский Владимир

Поиск Строка поискаЧтобы скрыть строку поиска из IE7, в разделе HKCUSoftwarePoliciesMicrosoftInternet ExplorerInfoDeliveryRestrictionsсоздайте параметр типа DWORD ·NoSearchBox· со значением 1. Перезапустите IE7, чтобы изменения вступили в силу. Кнопка Поиск (IE6)Чтобы изменить адрес поисковика, который у вас


Поиск

Из книги Тонкости реестра Windows Vista. Трюки и эффекты автора Клименко Роман Александрович

Поиск Чтобы начать поиск, следует выполнить команду меню Search ? Find/Replace (Поиск ? Найти/Заменить) или нажать сочетание клавиш Ctrl+F. В нижней части окна программы появится панель поиска.В поле Find (Найти) необходимо указать искомое слово (или выражение), а затем нажать кнопку Find All


Поиск

Из книги Советы по Delphi. Версия 1.0.6 автора Озеров Валентин

Поиск Управление отображением команды Поиск, которая также по умолчанию входит в состав меню кнопки Пуск, осуществляется в системном реестре в разделе HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionPoliciesExplorer с помощью REG_DWORD-параметра NoFind. Чтобы удалить данную функцию, следует присвоить


Поиск

Из книги Системное программирование в среде Windows автора Харт Джонсон М

Поиск Поиск величины при вводе Каким способом можно производить поиск подходящих величин в момент ввода? Табличный курсор (визуально) должен перемещаться к наиболее подходящему значению при добавлении пользователем новых символов водимой величины.Первоначально код


Управление памятью кучи

Из книги Программирование на языке Пролог для искусственного интеллекта автора Братко Иван

Управление памятью кучи Для получения блока памяти из кучи следует указать дескриптор области памяти кучи, размер блока и некоторые флаги.  LPVOID НеарАllос(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes) Возвращаемое значение: в случае успешного выполнения — указатель на распределенный блок


Другие функции кучи

Из книги Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/FireBird/Yaffil автора Ковязин Алексей Николаевич

Другие функции кучи Функция HeapCompact пытается уплотнить, или дефрагментировать, смежные блоки в куче. Функция HeapValidate пытается обнаруживать повреждения кучи. Функция HeapWalk перечисляет блоки в куче, а функция GetProcessHeaps получает все действительные дескрипторы куч.Функции HeapLock


Глава 12 Поиск с предпочтением: эвристический поиск

Из книги HTML5 для веб-дизайнеров автора Джереми Кит

Глава 12 Поиск с предпочтением: эвристический поиск Поиск в графах при решении задач, как правило, невозможен без решения проблемы комбинаторной сложности, возникающей из-за быстрого роста числа альтернатив. Эффективным средством борьбы с этим служит эвристический


Профилактика повреждений баз данных InterBase

Из книги Профессиональный поиск в Интернете автора Кутовенко Алексей

Профилактика повреждений баз данных InterBase Профилактические действия, которые следует производить для предотвращения поломок баз данных, - это постоянное создание резервных копий (подробно о резервном копировании см. главу "Резервное копирование и восстановление из


Поиск

Из книги Секреты приложений Google автора Балуев Денис

Поиск Элемент input со значением “search” в атрибуте type будет вести себя примерно так же, как элемент ввода со значением “text” атрибута type:<label for="query">Поиск</label><input id="query" name="query" type="search">Единственная разница между “text” и “search” состоит в том, что браузер может


Поиск на научных сайтах с использованием платформы Flexum «Поиск по научным сайтам»

Из книги Linux Mint и его Cinnamon. Очерки применителя автора Федорчук Алексей Викторович

Поиск на научных сайтах с использованием платформы Flexum «Поиск по научным сайтам» Тема научного поиска не прошла мимо разработчиков персональных поисковиков. Подробному рассказу о возможностях таких поисковых систем посвящена отдельная глава нашей книги (см. главу 6).


RSS-поиск

Из книги автора

RSS-поиск Пополнять список своего RSS-агрегатора можно различными способами. Первый и наиболее распространенный – простой поиск сайтов по интересующим темам, а затем подписка на их RSS-ленты, если, конечно таковые имеются. Способ несложный, однако на редкость медленный и


Поиск

Из книги автора

Поиск Поскольку каналы, на которые вы подписаны, в некотором роде являются вашей базой знаний, в ней нужно уметь эффективно ориентироваться – упорядочивать новости по типам, выделять запомнившиеся сообщения, искать нужные записи. Для этого Reader предлагает сразу


Поиск

Из книги автора

Поиск С количеством фотографий, производимых современными обладателями цифровиков, работа по разбору и классификации фотографий превращается в нетривиальное занятие: легкость съемки и дешевизна карт памяти привела к тому, что мы практически не удаляем снимки, даже