До сих пор моя программа работала неплохо, я хотел запустить valgrind, чтобы быть уверенным, что я не забыл никаких бесплатных/malloc. Тем не менее, Valgrind сообщил об ошибках, где я считаю, что их нет.Ошибка обнаружения Valgrind при распределении с использованием realloc и strdup
Вот фрагмент кода, чтобы воспроизвести ошибку:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
/* Init the array to NULL for realloc */
char **name_array = NULL;
int nb_names =0;
/* Allocate the first name and add it to the array */
name_array = realloc(name_array, sizeof(char *));
name_array[nb_names] = strdup("Hello World!\n");
nb_names++;
/* Allocate the second name and add it to the array */
name_array = realloc(name_array, sizeof(char *));
name_array[nb_names] = strdup("This is a test!\n");
/* Print the names */
printf (name_array[0]);
printf (name_array[1]);
/* Free the strdup'd names and the array */
free(name_array[0]);
free(name_array[1]);
free(name_array);
}
Это выход программы:
Hello World!
This is a test!
Вот выход Valgrind:
==31585== Memcheck, a memory error detector
==31585== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==31585== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==31585== Command: ./a.out --leak-check=full
==31585==
==31585== Invalid write of size 4
==31585== at 0x10538: main (in /home/pi/tmp/a.out)
==31585== Address 0x49830a4 is 0 bytes after a block of size 4 alloc'd
==31585== at 0x48358A0: realloc (vg_replace_malloc.c:632)
==31585== by 0x10517: main (in /home/pi/tmp/a.out)
==31585==
Hello World!
==31585== Invalid read of size 4
==31585== at 0x10554: main (in /home/pi/tmp/a.out)
==31585== Address 0x49830a4 is 0 bytes after a block of size 4 alloc'd
==31585== at 0x48358A0: realloc (vg_replace_malloc.c:632)
==31585== by 0x10517: main (in /home/pi/tmp/a.out)
==31585==
This is a test!
==31585== Invalid read of size 4
==31585== at 0x10578: main (in /home/pi/tmp/a.out)
==31585== Address 0x49830a4 is 0 bytes after a block of size 4 alloc'd
==31585== at 0x48358A0: realloc (vg_replace_malloc.c:632)
==31585== by 0x10517: main (in /home/pi/tmp/a.out)
==31585==
==31585==
==31585== HEAP SUMMARY:
==31585== in use at exit: 0 bytes in 0 blocks
==31585== total heap usage: 4 allocs, 4 frees, 39 bytes allocated
==31585==
==31585== All heap blocks were freed -- no leaks are possible
==31585==
==31585== For counts of detected and suppressed errors, rerun with: -v
==31585== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
Я искал other Q & Об этом ответе, обычно люди забывают выделить нулевой байт.
Я знаю, что realloc может вызвать утечку памяти, когда нет памяти, я должен сначала присвоить результат realloc временной переменной, проверить, что возвращаемое значение не равно null, а затем назначить временную переменную моим истинным переменным.
Аптека из возможной утечки при сбое realloc, есть ли ошибки в этой программе?
UPDATE
Спасибо ребята за быстрые ответы.
Для записи здесь исправленный код:
/* Allocate the first name and add it to the array */
name_array = realloc(name_array, sizeof(char *) * ++nb_names);
name_array[nb_names -1] = strdup("Hello World!\n");
/* Allocate the second name and add it to the array */
name_array = realloc(name_array, sizeof(char *) * ++nb_names);
name_array[nb_names -1] = strdup("This is a test!\n");
/* Print the names */
printf (name_array[0]);
printf (name_array[1]);
И выход Valgrind:
==32105== Memcheck, a memory error detector
==32105== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==32105== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==32105== Command: ./a.out
==32105==
Hello World!
This is a test!
==32105==
==32105== HEAP SUMMARY:
==32105== in use at exit: 0 bytes in 0 blocks
==32105== total heap usage: 4 allocs, 4 frees, 43 bytes allocated
==32105==
==32105== All heap blocks were freed -- no leaks are possible
==32105==
==32105== For counts of detected and suppressed errors, rerun with: -v
==32105== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Добрый день всем.
Ваш второй realloc не увеличивает размер массива. –
'name_array = realloc (name_array, sizeof (char *));' => 'name_array = realloc (name_array, sizeof * name_array * ++ nb_names);'. – Stargateur
Кроме того, 'name_array = realloc (name_array, ...)' является потенциальной утечкой памяти. И убедитесь, что 'malloc()' не возвратил 'NULL'. –