Valgrind сообщает об утечке памяти на освобожденном указателе после getline от stdin - PullRequest
1 голос
/ 02 ноября 2019

Имея этот код:

#include <stdlib.h>
#include <stdio.h>
void main()
{   
    char *line = calloc(1024, 1);
    size_t size = 0;
    getline(&line, &size, stdin);
    free(line);
}

Valgrind жалуется:

==5931== HEAP SUMMARY:
==5931==     in use at exit: 1,024 bytes in 1 blocks
==5931==   total heap usage: 3 allocs, 2 frees, 2,168 bytes allocated
==5931== 
==5931== 1,024 bytes in 1 blocks are definitely lost in loss record 1 of 1
==5931==    at 0x4837B65: calloc (vg_replace_malloc.c:752)
==5931==    by 0x10916B: main (test.c:5)
==5931== 
==5931== LEAK SUMMARY:
==5931==    definitely lost: 1,024 bytes in 1 blocks

Я видел другие похожие посты, но не смог найти ответ на этот конкретный случай: /

Ответы [ 3 ]

3 голосов
/ 02 ноября 2019

Это ошибка glibc (или давнее поведение glibc, в зависимости от того, как вы на это смотрите):

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

0 голосов
/ 02 ноября 2019

Размер, содержащийся в size - это размер текущего распределения, на который указывает line. Таким образом, исправление будет

#include <stdlib.h>
#include <stdio.h>
int main(void)
{   
    char *line = calloc(1024, 1);
    size_t size = 1024;
    getline(&line, &size, stdin);
    free(line);
}

, и это будет нормально!

В качестве альтернативы вы можете сделать

char *line = NULL;
size_t size = 0;
getline(&line, &size, stdin);
free(line);

, но это может сделать некоторые дополнительные перераспределения для строк, которыедлиной 1000 символов.

0 голосов
/ 02 ноября 2019

Оба getline и calloc выделяют память. Если вы хотите использовать getline, не выделяйте заранее. Просто сделайте это:

int main(void)
{   
    char *line = NULL;
    size_t size = 0;
    getline(&line, &size, stdin);
    free(line);
}

Намек на это, как вы называете getline. Если вы отправляете line, функция не сможет изменить то, на что указывает указатель. Но теперь вы отправляете &line, что означает, что функция хочет перераспределить память.

Если вы хотите перераспределить, используйте fgets вместо getline.

Кроме того,main не должно быть функцией void.

...