Как использовать valgrind для поиска утечек памяти в программе?
Пожалуйста, помогите мне и опишите шаги для выполнения процедуры?
Я использую Ubuntu 10.04, и у меня есть программа a.c
, пожалуйста, помогите мне.
Как использовать valgrind для поиска утечек памяти в программе?
Пожалуйста, помогите мне и опишите шаги для выполнения процедуры?
Я использую Ubuntu 10.04, и у меня есть программа a.c
, пожалуйста, помогите мне.
Попробуйте следующее:
valgrind --leak-check=full -v ./your_program
Пока valgrind установлен, он будет проходить через вашу программу и сообщать вам, что неправильно. Он может дать вам указатели и приблизительные места, где могут быть обнаружены утечки. Если вы segfault'ing, попробуйте запустить его через gdb
.
Вы можете запустить:
valgrind --leak-check=full --log-file="logfile.out" -v [your_program(and its arguments)]
Я хотел бы основать на RageD отличный ответ, предоставив более подробное объяснение того, как эффективно использовать Valgrind и как разрешать утечки памяти. Чтобы не оскорблять OP, но для тех, кто пришел к этому вопросу и до сих пор не знаком с Linux - , вам может понадобиться установить Valgrind в вашей системе.
sudo apt-get install valgrind #mainly Ubuntu
sudo yum install valgrind #RHEL, CentOS, Fedora, etc.
Valgrind легко используется для кода C/С++, но может даже использоваться для других языков при правильной настройке (см. this для Python).
Чтобы запустить valgrind, передайте исполняемый файл в качестве аргумента (вместе с любыми параметрами для программы).
valgrind --leak-check=full \
--show-leak-kinds=all \
--track-origins=yes \
--verbose \
--log-file=valgrind-out.txt \
./executable exampleParam1
Это приведет к созданию отчета в конце выполнения вашей программы, который (надеюсь) выглядит следующим образом:
HEAP SUMMARY:
in use at exit: 0 bytes in 0 blocks
total heap usage: 636 allocs, 636 frees, 25,393 bytes allocated
All heap blocks were freed -- no leaks are possible
ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Итак, у вас есть утечка памяти, и Valgrind не говорит ничего значимого. Возможно, что-то вроде этого:
5 bytes in 1 blocks are definitely lost in loss record 1 of 1
at 0x4C29BE3: malloc (vg_replace_malloc.c:299)
by 0x40053E: main (in /home/Peri461/Documents/executable)
Посмотрим также на код C, который я написал:
#include <stdlib.h>
int main() {
char* string = malloc(5 * sizeof(char)); //ERROR: not freed!
return 0;
}
Ну, было потеряно 5 байт. Как это произошло? Отчет об ошибке сообщает только main
и malloc
. В более крупной программе было бы тяжело хлопотать о выслежении. Это связано с тем, как скомпилирован исполняемый файл. Мы можем фактически получить подробные данные о том, что пошло не так. Перекомпилируйте свою программу с флагом отладки (здесь я использую gcc
):
gcc -o executable -std=c11 -Wall main.c #suppose it was this at first
gcc -o executable -std=c11 -Wall -ggdb3 main.c #add -ggdb3 to it
Теперь посмотрим, что сделал Valgrind с нашей сборкой отладки:
5 bytes in 1 blocks are definitely lost in loss record 1 of 1
at 0x4C29BE3: malloc (vg_replace_malloc.c:299)
by 0x40053E: main (main.c:4)
Valgrind указал нам на точную строку кода, вызывающую утечку памяти!
gdb
возможно), и ищите ошибки предварительного условия/постусловия.60 bytes in 1 blocks are definitely lost in loss record 1 of 1
at 0x4C2BB78: realloc (vg_replace_malloc.c:785)
by 0x4005E4: resizeArray (main.c:12)
by 0x40062E: main (main.c:19)
И код:
#include <stdlib.h>
#include <stdint.h>
struct _List {
int32_t* data;
int32_t length;
};
typedef struct _List List;
List* resizeArray(List* array) {
int32_t* dPtr = array->data;
dPtr = realloc(dPtr, 15 * sizeof(int32_t)); //doesn't update array->data
return array;
}
int main() {
List* array = calloc(1, sizeof(List));
array->data = calloc(10, sizeof(int32_t));
array = resizeArray(array);
free(array->data);
free(array);
return 0;
}
Как помощник преподавателя, я часто видел эту ошибку. Учащийся использует локальную переменную и забывает обновлять исходный указатель. Ошибка здесь замечает, что realloc
может фактически переместить выделенную память в другое место и изменить местоположение указателя. Затем мы оставляем resizeArray
без указания array->data
, где массив был перемещен в.
1 errors in context 1 of 1:
Invalid write of size 1
at 0x4005CA: main (main.c:10)
Address 0x51f905a is 0 bytes after a block of size 26 alloc'd
at 0x4C2B975: calloc (vg_replace_malloc.c:711)
by 0x400593: main (main.c:5)
И код:
#include <stdlib.h>
#include <stdint.h>
int main() {
char* alphabet = calloc(26, sizeof(char));
for(uint8_t i = 0; i < 26; i++) {
*(alphabet + i) = 'A' + i;
}
*(alphabet + 26) = '\0'; //null-terminate the string?
free(alphabet);
return 0;
}
Обратите внимание, что Valgrind указывает нам на прокомментированную строку кода выше. Массив размера 26 индексируется [0,25], поэтому *(alphabet + 26)
является недопустимой записью - это вне границ. Недопустимая запись - это общий результат ошибок "один за другим". Посмотрите на левую часть операции назначения.
1 errors in context 1 of 1:
Invalid read of size 1
at 0x400602: main (main.c:9)
Address 0x51f90ba is 0 bytes after a block of size 26 alloc'd
at 0x4C29BE3: malloc (vg_replace_malloc.c:299)
by 0x4005E1: main (main.c:6)
И код:
#include <stdlib.h>
#include <stdint.h>
int main() {
char* destination = calloc(27, sizeof(char));
char* source = malloc(26 * sizeof(char));
for(uint8_t i = 0; i < 27; i++) {
*(destination + i) = *(source + i); //Look at the last iteration.
}
free(destination);
free(source);
return 0;
}
Вальгринд указывает нам на прокомментированную строку выше. Посмотрите на последнюю итерацию, которая есть *(destination + 26) = *(source + 26);
. Однако *(source + 26)
снова выходит за пределы, аналогично недействительной записи. Неверные чтения также являются общим результатом ошибок "один за другим". Посмотрите на правую сторону операции назначения.