Майкл Джонсон - Разработка приложений в среде Linux. Второе издание
- Название:Разработка приложений в среде Linux. Второе издание
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2007
- Город:Москва
- ISBN:978-5-8459-1143-8
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Майкл Джонсон - Разработка приложений в среде Linux. Второе издание краткое содержание
Книга известных профессионалов в области разработки коммерческих приложений в Linux представляет собой отличный справочник для широкого круга программистов в Linux, а также тех разработчиков на языке С, которые перешли в среду Linux из других операционных систем. Подробно рассматриваются концепции, лежащие в основе процесса создания системных приложений, а также разнообразные доступные инструменты и библиотеки. Среди рассматриваемых в книге вопросов можно выделить анализ особенностей применения лицензий GNU, использование свободно распространяемых компиляторов и библиотек, системное программирование для Linux, а также написание и отладка собственных переносимых библиотек. Изобилие хорошо документированных примеров кода помогает лучше усвоить особенности программирования в Linux.
Книга рассчитана на разработчиков разной квалификации, а также может быть полезна для студентов и преподавателей соответствующих специальностей.
Разработка приложений в среде Linux. Второе издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
7.2.2. Использование mtrace()для отслеживания распределений памяти
Один из простых способов нахождения всех утечек памяти в программе предусматривает регистрацию всех вызовов malloc()и free(). По окончании программы очень легко сопоставить блоки, распределенные через malloc(), с точками, где они были освобождены с помощью free()или сообщить об ошибке, если для какого-то блока free()не вызывалась.
В отличие от mcheck(), в mtrace()нет соответствующей библиотеки для компоновки. Это не проблема, поскольку трассировку можно осуществлять в gdb. Однако для включения трассировки с помощью mtrace()должна быть установлена переменная окружения MALLOC_TRACEв допустимое имя файла; это может быть либо имя существующего файла, в который процесс может вести запись, либо имя нового файла, который процесс создаст и будет в него записывать.
$ MALLOC_TRACE=mtrace.log gdb broken
...
(gdb) breakmain
Breakpoint 1 at 0x80483f4: filebroken.c, line 14.
(gdb) command 1
Type commands for when Breakpoint 1 is hit, one per line.
End with a line saying just "end".
>call mtrace()
>continue
>end
(gdb) run
Starting program: /usr/src/lad/code/broken
Breakpoint 1, main() at broken.с:47
47 return broken();
$1 = 0
1: 12345
2: 12345678
3: 12345678
4: 12345
5: 12345
6: 12345
7: 12345
Program exited normally.
Программа завершена нормально.
(gdb) quit
$ ls -l mtrace.log
-rw-rw-r-- 1 ewt ewt 220 Dec 27 23:41 mtrace.log
$ mtrace ./broken mtrace.log
Memory not freed:
He освобождена память:
----------------------
Address Size Caller
Адрес Размер Место вызова
0x09211378 0x5 at /usr/src/lad/code/broken.с:20
Обратите внимание, что программа mtraceточно обнаружила утечку памяти. Также она может найти факт освобождения с помощью free()памяти, которая ранее не распределялась, если этот факт будет зафиксирован в журнальном файле, но на практике так не происходит, поскольку в этом случае программа немедленно аварийно завершается.
7.3. Поиск утечек памяти с помощью mpr
Возможности mtrace()в glibcдостаточно неплохие, но профилировщик распределения памяти mpr(http://www3.telus.net/taj_khattra/mpr.html) в некоторых аспектах более прост в использовании и содержит более совершенные сценарии для обработки выходных журнальных файлов.
Первый шаг в применении mpr(после сборки кода с включенной отладочной информацией [10] Для большей переносимости многие из средств mpr анализа журнала используют gdb для связывания адреса с соответствующим местом в исходном коде. Чтобы это работало, программа должна содержать отладочную информацию.
) состоит в установке переменной окружения MPRFI, которая указывает mpr, с какой командой связывать журнал (если переменная не установлена, журнал не генерируется). Для небольших программ MPRFIустанавливается подобно cat >mpr.log. Для программ покрупнее MPRFIможно существенно сэкономить пространство за счет сжатия журнального файла во время его записи, установив MPRFIв gzip -1 >mpr.log.gz.
Самый легкий способ — воспользоваться сценарием mprдля запуска программы; если MPRFIеще не установлена, она получит значение gzip -1 >log.%p.gz, что приведет к созданию журнального файла с идентификатором процесса отлаживаемой программы и загрузке библиотеки mpr. В результате сборка программы не понадобится. Ниже показан пример создания журнального файла для исправленной версии нашей тестовой программы.
$ MPRFI="cat >mpr.log" mpr ./broken
1: 12345
2: 12345678
3: 12345678
4: 12345
5: 12345
6: 12345
7: 12345
$ ls -l mpr.log
-rw-rw-r-- 1 ewt ewt 142 May 17 16:22 mpr.log
После создания журнального файла доступны многие средства для его анализа. Все эти программы получают журнальный файл mpr в качестве стандартного ввода. Если вывод из этих средств содержит числа в тех местах, где ожидаются имена функций (возможно, с предупреждением вроде "cannot map pc to name" ("невозможно отобразить программный счетчик на имя")), проблема может быть связана с версией утилиты awk, которую использует mpr. В документации mprдля достижения лучших результатов рекомендуется экспортировать переменную окружения MPRAWKдля выбора mawkв качестве версии awk: export MPRAWK='mawk -W sprintf=4096'. Кроме того, сбить с толку mpr может еще и рандомизация стека, которая обеспечивается функциональностью ядра "Exec-shield"; исправить положение можно за счет использования команды setarch, отключающей Exec-shield во время работы исследуемой программы и во время работы фильтров mpr: setarch i386 mpr программа и setarch i386 mprmap ...
В конечном итоге для некоторых стековых фреймов mprможет не найти символическое имя; в этом случае просто проигнорируйте их.
mprmap программа |
Преобразует адреса программы в журнале mprв имена функций и местоположения в исходном коде. В аргументе указывается имя исполняемого файла, для которого должен генерироваться журнал. Чтобы увидеть все распределения в программе вместе с цепочкой вызовов функций, которые осуществили эти распределения, можно использовать mprmap программа < mpr.log. По умолчанию отображаются имена функций. При указании флажка -fотображаются также имена файлов, а при указании -l— еще и номера строк внутри файлов. Флажок -lподразумевает наличие -f. Вывод этой программы является допустимым журнальным файлом mpr, который может быть связан каналом с любой другой утилитой mpr. |
mprchain |
Преобразует журнал в вывод, сгруппированный по цепочкам вызовов. Цепочка вызовов функций — это список всех функций, активных в программе на определенный момент. Например, если main()вызывает getargs(), которая впоследствии вызывает parsearg(), активная цепочка вызовов во время работы parsearg()отображается как main:getargs:parsearg. Для каждой отдельной цепочки вызовов, в которой распределялась память во время выполнения программы, mprchain отображает количество распределений и общее количество распределенных байт. |
mprleak |
Этот фильтр просматривает журнальный файл на предмет наличия всех неосвобожденных фрагментов памяти. В качестве стандартного вывода генерируется новый журнальный файл, содержащий только те распределения, которые могут привести к утечкам памяти. Вывод этой программы является допустимым журнальным файлом mpr, который может быть связан каналом с любой другой утилитой mpr. |
mprsize |
Этот фильтр сортирует распределения памяти по размеру. Чтобы просмотреть утечки памяти по размеру, нужно передать вывод mprleakна вход mprsize. |
mprhisto |
Отображает гистограмму распределений памяти. |
Теперь, когда известно об анализаторах журнальных файлов, очень просто найти утечки памяти в нашей тестовой программе. Для этого достаточно воспользоваться командой mprleak mpr.log | mprmap -l ./broken(что эквивалентно mprmap -l ./broken mpr.log | mprleak) и в результате обнаружить утечку памяти в строке 20.
Интервал:
Закладка: