Valgrind 在使用 realloc 和 strdup 进行分配时检测到错误
Valgrind detect error when allocating using realloc and strdup
到目前为止,我的程序运行良好,我想 运行 valgrind 以确保我没有忘记任何 free/malloc。但是,Valgrind 报告了我认为存在 none.
的错误
这是重现错误的代码片段:
#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)
我已经搜索过关于这个答案的其他问答,通常人们会忘记分配空字节。
我知道realloc在没有内存时会导致内存泄漏,我应该先将realloc的结果赋值给一个临时变量,检查返回值不为null,然后将临时变量赋值给我的真实变量。
除了realloc失败时可能会泄露,这个程序有没有错误?
更新
感谢大家的快速回答。
这里记录的是更正后的代码:
/* 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)
大家好。
这次(第二次)通话:
name_array = realloc(name_array, sizeof(char *));
您仍然只分配一个字符指针。所以,你不能存储两个指针;你需要增加尺寸:
name_array = realloc(name_array, 2 * sizeof *name_array);
现在,你会没事的。
请注意,如果 realloc()
失败,p = realloc(p, ..);
风格的 realloc() 可能会导致内存泄漏。
此外,您最好使用格式字符串来避免潜在的格式字符串攻击(如果它将由用户输入):
/* Print the names */
printf ("%s\n", name_array[0]);
printf ("%s\n", name_array[1]);
地址清理器比 valgrind 更能报告错误。如果您像这样编译代码:
gcc test.c -fsanitize=address -g
然后运行它,它会在你的代码第19行报heap-buffer-overflow错误。这是您分配 name_array 的第二个元素的行,只为一个元素分配了内存。
到目前为止,我的程序运行良好,我想 运行 valgrind 以确保我没有忘记任何 free/malloc。但是,Valgrind 报告了我认为存在 none.
的错误这是重现错误的代码片段:
#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)
我已经搜索过关于这个答案的其他问答,通常人们会忘记分配空字节。
我知道realloc在没有内存时会导致内存泄漏,我应该先将realloc的结果赋值给一个临时变量,检查返回值不为null,然后将临时变量赋值给我的真实变量。
除了realloc失败时可能会泄露,这个程序有没有错误?
更新
感谢大家的快速回答。
这里记录的是更正后的代码:
/* 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)
大家好。
这次(第二次)通话:
name_array = realloc(name_array, sizeof(char *));
您仍然只分配一个字符指针。所以,你不能存储两个指针;你需要增加尺寸:
name_array = realloc(name_array, 2 * sizeof *name_array);
现在,你会没事的。
请注意,如果 realloc()
失败,p = realloc(p, ..);
风格的 realloc() 可能会导致内存泄漏。
此外,您最好使用格式字符串来避免潜在的格式字符串攻击(如果它将由用户输入):
/* Print the names */
printf ("%s\n", name_array[0]);
printf ("%s\n", name_array[1]);
地址清理器比 valgrind 更能报告错误。如果您像这样编译代码:
gcc test.c -fsanitize=address -g
然后运行它,它会在你的代码第19行报heap-buffer-overflow错误。这是您分配 name_array 的第二个元素的行,只为一个元素分配了内存。