【发布时间】:2025-12-26 06:30:11
【问题描述】:
我试图运行一个使用函数concat_str 的程序。它可以接受多个参数作为字符串,参数的结尾由"quit" 表示。我的函数代码如下:
char *concat_str(char *str1, ...)
{
va_list pstr;
char *minion = NULL, *temp = NULL;
minion = (char*) malloc (sizeof(str1));
strcpy (minion,str1);
va_start (pstr, str1);
if ( strcmp ("quit",str1) == 0)
{
va_end (pstr);
return minion;
}
while (1)
{
temp = va_arg (pstr, char *);
if ( strcmp ("quit", temp) == 0)
{
break;
}
minion = (char*) realloc (minion, sizeof(temp));
strncat (minion,temp,sizeof(temp));
}
va_end (pstr);
return minion;
}
同样的调用语句是:
char *result;
result = concat_str("hello", "hai", "how", "are", "you", "quit");
我确实得到了正确的输出。但是当我使用memcheck 工具在valgrind 上运行它时,我遇到了很多错误。错误如下:
==2635== Invalid write of size 1
==2635== at 0x4A065D3: strncat (mc_replace_strmem.c:218)
==2635== by 0x400A7E: concat_str (var_fun.c:23)
==2635== by 0x400757: main (var_main.c:15)
==2635== Address 0x4C33038 is 0 bytes after a block of size 8 alloc'd
==2635== at 0x4A0590B: realloc (vg_replace_malloc.c:306)
==2635== by 0x400A5F: concat_str (var_fun.c:22)
==2635== by 0x400757: main (var_main.c:15)
==2635==
==2635== Invalid read of size 1
==2635== at 0x4A06594: strncat (mc_replace_strmem.c:218)
==2635== by 0x400A7E: concat_str (var_fun.c:23)
==2635== by 0x400757: main (var_main.c:15)
==2635== Address 0x4C33038 is 0 bytes after a block of size 8 alloc'd
==2635== at 0x4A0590B: realloc (vg_replace_malloc.c:306)
==2635== by 0x400A5F: concat_str (var_fun.c:22)
==2635== by 0x400757: main (var_main.c:15)
==2635==
==2635== Invalid write of size 1
==2635== at 0x4A065BF: strncat (mc_replace_strmem.c:218)
==2635== by 0x400A7E: concat_str (var_fun.c:23)
==2635== by 0x400757: main (var_main.c:15)
==2635== Address 0x4C33038 is 0 bytes after a block of size 8 alloc'd
==2635== at 0x4A0590B: realloc (vg_replace_malloc.c:306)
==2635== by 0x400A5F: concat_str (var_fun.c:22)
==2635== by 0x400757: main (var_main.c:15)
==2635==
==2635== Invalid read of size 1
==2635== at 0x4A066D4: strlen (mc_replace_strmem.c:246)
==2635== by 0x32DAC46B18: vfprintf (in /lib64/libc-2.5.so)
==2635== by 0x32DAC4D3A9: printf (in /lib64/libc-2.5.so)
==2635== by 0x40076E: main (var_main.c:16)
==2635== Address 0x4C33038 is 0 bytes after a block of size 8 alloc'd
==2635== at 0x4A0590B: realloc (vg_replace_malloc.c:306)
==2635== by 0x400A5F: concat_str (var_fun.c:22)
==2635== by 0x400757: main (var_main.c:15)
==2635==
==2635== Invalid read of size 1
==2635== at 0x32DAC6CE09: _IO_file_xsputn@@GLIBC_2.2.5 (in /lib64/libc-2.5.so)
==2635== by 0x32DAC464B2: vfprintf (in /lib64/libc-2.5.so)
==2635== by 0x32DAC4D3A9: printf (in /lib64/libc-2.5.so)
==2635== by 0x40076E: main (var_main.c:16)
==2635== Address 0x4C33040 is 8 bytes after a block of size 8 alloc'd
==2635== at 0x4A0590B: realloc (vg_replace_malloc.c:306)
==2635== by 0x400A5F: concat_str (var_fun.c:22)
==2635== by 0x400757: main (var_main.c:15)
==2635==
==2635== Invalid read of size 1
==2635== at 0x32DAC6CE1C: _IO_file_xsputn@@GLIBC_2.2.5 (in /lib64/libc-2.5.so)
==2635== by 0x32DAC464B2: vfprintf (in /lib64/libc-2.5.so)
==2635== by 0x32DAC4D3A9: printf (in /lib64/libc-2.5.so)
==2635== by 0x40076E: main (var_main.c:16)
==2635== Address 0x4C3303F is 7 bytes after a block of size 8 alloc'd
==2635== at 0x4A0590B: realloc (vg_replace_malloc.c:306)
==2635== by 0x400A5F: concat_str (var_fun.c:22)
==2635== by 0x400757: main (var_main.c:15)
==2635==
==2635== Invalid read of size 1
==2635== at 0x32DAC6CD66: _IO_file_xsputn@@GLIBC_2.2.5 (in /lib64/libc-2.5.so)
==2635== by 0x32DAC464B2: vfprintf (in /lib64/libc-2.5.so)
==2635== by 0x32DAC4D3A9: printf (in /lib64/libc-2.5.so)
==2635== by 0x40076E: main (var_main.c:16)
==2635== Address 0x4C33038 is 0 bytes after a block of size 8 alloc'd
==2635== at 0x4A0590B: realloc (vg_replace_malloc.c:306)
==2635== by 0x400A5F: concat_str (var_fun.c:22)
==2635== by 0x400757: main (var_main.c:15)
==2635==
==2635== Invalid read of size 1
==2635== at 0x32DAC6CD7A: _IO_file_xsputn@@GLIBC_2.2.5 (in /lib64/libc-2.5.so)
==2635== by 0x32DAC464B2: vfprintf (in /lib64/libc-2.5.so)
==2635== by 0x32DAC4D3A9: printf (in /lib64/libc-2.5.so)
==2635== by 0x40076E: main (var_main.c:16)
==2635== Address 0x4C33039 is 1 bytes after a block of size 8 alloc'd
==2635== at 0x4A0590B: realloc (vg_replace_malloc.c:306)
==2635== by 0x400A5F: concat_str (var_fun.c:22)
==2635== by 0x400757: main (var_main.c:15)
错误来源(我自己的推论):
第 22 行:minion = (char*) realloc (minion, sizeof(temp));
Realloc 将新块的指针地址返回到minion。但是旧块会产生问题。
我尝试过的事情:
我将
strncat (minion,temp,sizeof(temp));更改为strncat (minion,temp,sizeof(temp) + 10);。这减少了一些错误。但是如果字符串参数很长,我又会遇到同样的错误。顺便说一句,我不明白这是如何解决问题的。-
我把
minion = (char*) realloc (minion, sizeof(temp));改成了字符 t = NULL; t = 奴才; minion = (char) realloc (t, sizeof(temp)); 免费(t);
请告诉我,如果我的错误来源是正确的,并建议我应该如何解决这个问题。
【问题讨论】:
-
注意:不要在代码中粘贴行号。也适用于
minion = (char*) malloc (sizeof(str1));不要转换 malloc 的结果。在这里你需要strlen而不是sizeof。 -
不要将
realloc的结果分配给您重新分配的同一个指针。想想如果realloc失败并返回NULL会发生什么,那么您将丢失原始指针并发生内存泄漏(除了您根本不检查失败的事实之外)。 -
@JoachimPileborg。请阅读我尝试过的东西,第二点。
-
@JoachimPileborg 我实际上是在我的主函数中调用免费(结果)
-
调用
free没关系,因为任何分配函数都失败了,你会得到一个NULL指针。并且您应该以相反的顺序进行重新分配/分配,即将realloc结果分配给t,然后如果不是NULL,则将t分配给minion。而你还是should not cast the result ofmalloc(and family)。
标签: c variables arguments valgrind realloc