Блог о математике, программировании, алгоритмах. И немного о работе операционной системы Linux.

суббота, 22 октября 2011 г.

Утечки памяти, malloc и valgrind.

Утечки памяти — это ситуации, при которых выделенная в процессе выполнения программы память не освобождается, а указатель на эту память затирается. Вообще говоря, существует два базовых способа отладки как таковой. Отладка с исползованием сторонних средств (таких, например, как GDB) и отладка с использованием отладочных выводов (MessageBox-ами или выводом в консоль).

Способ первый.
Для локализации утечек памяти под Linux-ом (для программ скомпилированных GCC) есть прекрасное средство valgrind. Для того, чтобы проанализировать приложение нужно сделать следующее:
valgrind --tool=memcheck --leak-check=full --log-file=<log file name> <program name>
Здесь <log file name> имя файла в который будет записан вывод анализатора, а <program name> — название вашего приложения (и путь к нему). Стоит отметить, что для того, чтобы valgrind смог произвести анализ, нужно, чтобы ваше приложение было собрано с отладочной информацией для отладчика GDB (ключ -g компилятора). Так же стоит заметить, что valgrind запускает приложение в собственной виртуальной среде, что позволяет отследить все ошибки сегментации (приложение не вылетит, и закончит свое выполнение). Вывод valgrind-а имеет примерно следующий вид:
==5454== Memcheck, a memory error detector
==5454== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==5454== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==5454== Command: ./calc
==5454== Parent PID: 3856
==5454== 
==5454== 
==5454== HEAP SUMMARY:
==5454==     in use at exit: 252 bytes in 24 blocks
==5454==   total heap usage: 60,776 allocs, 60,752 frees, 269,156 bytes allocated
==5454== 
==5454== 126 (16 direct, 110 indirect) bytes in 1 blocks are definitely lost in loss record 7 of 8
==5454==    at 0x402425F: calloc (vg_replace_malloc.c:467)
==5454==    by 0x80498CA: allocateMatrix (calc.c:476)
==5454==    by 0x804981E: loadMatrix (calc.c:454)
==5454==    by 0x8049F15: main (calc.c:669)
==5454== 
==5454== 126 (16 direct, 110 indirect) bytes in 1 blocks are definitely lost in loss record 8 of 8
==5454==    at 0x402425F: calloc (vg_replace_malloc.c:467)
==5454==    by 0x80498CA: allocateMatrix (calc.c:476)
==5454==    by 0x804981E: loadMatrix (calc.c:454)
==5454==    by 0x8049F25: main (calc.c:670)
==5454== 
==5454== LEAK SUMMARY:
==5454==    definitely lost: 32 bytes in 2 blocks
==5454==    indirectly lost: 220 bytes in 22 blocks
==5454==      possibly lost: 0 bytes in 0 blocks
==5454==    still reachable: 0 bytes in 0 blocks
==5454==         suppressed: 0 bytes in 0 blocks
==5454== 
==5454== For counts of detected and suppressed errors, rerun with: -v
==5454== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 20 from 7) 
Здесь число стоящее между символами «==» — это PID потока, а блоки которые начинаются с числа 126 — сообщения о найденых утечках памяти. 126 здесь — это число утеряных байт, а ниже приведен стек вызовов, который привел к утечке. В каждой строчке стека вызовов есть информация о том, в каком файле и в какой строке был сделан данный вызов. Ниже приводится ссумарная информация об ошибках и утечках. Подробнее про valgrind можно прочитать на официальном сайте (англ.).

Способ второй.
Однако, если программа мала или нет возможности использовать valgrind, можно воспользоваться более «низкоуровневым» способом отладки. Если ваша программа написана на C, с использованием стандартного malloc, тогда вы в любой момент времени, можете спросить сколько памяти уже выделено malloc-ом. Для этого используется структура mallinfo. Работу с ней можно организовать, например, таким образом:
#include <malloc.h>

int
main()
{
    struct mallinfo info;
    info = mallinfo();
    printf("%d\n", info.uordblks);
    /**
     * Здесь происходит что-то, через что течет память.
     */
    printf("%d\n", info.uordblks);
    return 0;
}
Функция mallinfo возвращает информацию о работе менеджера памяти в структуру mallinfo. Эта структура содержит поле uordblks, которое хранит количество байт, которое было выделено malloc.

Комментариев нет:

Отправить комментарий