[英]C: Concatenating Dynamically Allocated Strings
I have searched high and low for an applicable answer, but I couldn't find one.我已经搜索了一个适用的答案,但我找不到一个。 I am well aware my inability to solve this issue is due to a unfamiliarity of C.我很清楚我无法解决这个问题是由于不熟悉 C。
I am working on a function to concatenate one dynamically allocated string onto another, and it seems to work outside the realm of memory leaks and valgrind;我正在研究 function 以将一个动态分配的字符串连接到另一个,它似乎在 memory 泄漏和 valgrind 的 realm 之外工作; however, when I run it with valgrind it is evident I have some glaring memory leaks I just cannot find.但是,当我使用 valgrind 运行它时,很明显我有一些明显的 memory 泄漏,我只是找不到。 It seems to be a issue with how I am using realloc.我如何使用 realloc 似乎是个问题。
here is the code:这是代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void dynamCat(char *dest, const char *src) {
size_t len = strlen(dest) + strlen(src) + 1;
printf("strLen: %ld\n", len);
char *tmp = realloc(dest, len);
if(tmp == NULL){
fprintf(stderr, "strAppend: realloc messed up\n");
free(tmp);
return;
} else {
dest = tmp;
}
strcat(dest, src);
}
int main (int argc, char *argv[]) {
char *one = malloc(4);
strcpy(one, "tee");
char *two = malloc(4);
strcpy(two, "hee");
printf("one: %s\n", one);
printf("two: %s\n", two);
dynamCat(one, two);
printf("one: %s\n", one);
printf("two: %s\n", two);
//freeee
free(one);
free(two);
return 0;
}
the output on the command line:命令行上的 output:
$ ./dynamCat
one: tee
two: hee
strLen: 7
one: teehee
two: hee
here's where the bad stuff comes.这就是坏东西来的地方。
output with valgrind on the commandline: output 在命令行上使用 valgrind:
==28804== Memcheck, a memory error detector
==28804== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==28804== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==28804== Command: ./dynamCat
==28804==
==28804== Invalid read of size 1
==28804== at 0x4841C72: strlen (vg_replace_strmem.c:459)
==28804== by 0x48D9407: __vfprintf_internal (in /usr/lib/libc-2.33.so)
==28804== by 0x48C463E: printf (in /usr/lib/libc-2.33.so)
==28804== by 0x1092EE: main (dynamCat.c:37)
==28804== Address 0x4a3c040 is 0 bytes inside a block of size 4 free'd
==28804== at 0x4840D7B: realloc (vg_replace_malloc.c:834)
==28804== by 0x1091FA: dynamCat (dynamCat.c:11)
==28804== by 0x1092D6: main (dynamCat.c:35)
==28804== Block was alloc'd at
==28804== at 0x483E77F: malloc (vg_replace_malloc.c:307)
==28804== by 0x10926D: main (dynamCat.c:26)
==28804==
==28804== Invalid read of size 1
==28804== at 0x4841C84: strlen (vg_replace_strmem.c:459)
==28804== by 0x48D9407: __vfprintf_internal (in /usr/lib/libc-2.33.so)
==28804== by 0x48C463E: printf (in /usr/lib/libc-2.33.so)
==28804== by 0x1092EE: main (dynamCat.c:37)
==28804== Address 0x4a3c041 is 1 bytes inside a block of size 4 free'd
==28804== at 0x4840D7B: realloc (vg_replace_malloc.c:834)
==28804== by 0x1091FA: dynamCat (dynamCat.c:11)
==28804== by 0x1092D6: main (dynamCat.c:35)
==28804== Block was alloc'd at
==28804== at 0x483E77F: malloc (vg_replace_malloc.c:307)
==28804== by 0x10926D: main (dynamCat.c:26)
==28804==
==28804== Invalid read of size 1
==28804== at 0x48460D0: mempcpy (vg_replace_strmem.c:1536)
==28804== by 0x48ED211: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib/libc-2.33.so)
==28804== by 0x48D915A: __vfprintf_internal (in /usr/lib/libc-2.33.so)
==28804== by 0x48C463E: printf (in /usr/lib/libc-2.33.so)
==28804== by 0x1092EE: main (dynamCat.c:37)
==28804== Address 0x4a3c042 is 2 bytes inside a block of size 4 free'd
==28804== at 0x4840D7B: realloc (vg_replace_malloc.c:834)
==28804== by 0x1091FA: dynamCat (dynamCat.c:11)
==28804== by 0x1092D6: main (dynamCat.c:35)
==28804== Block was alloc'd at
==28804== at 0x483E77F: malloc (vg_replace_malloc.c:307)
==28804== by 0x10926D: main (dynamCat.c:26)
==28804==
==28804== Invalid read of size 1
==28804== at 0x48460DE: mempcpy (vg_replace_strmem.c:1536)
==28804== by 0x48ED211: _IO_file_xsputn@@GLIBC_2.2.5 (in /usr/lib/libc-2.33.so)
==28804== by 0x48D915A: __vfprintf_internal (in /usr/lib/libc-2.33.so)
==28804== by 0x48C463E: printf (in /usr/lib/libc-2.33.so)
==28804== by 0x1092EE: main (dynamCat.c:37)
==28804== Address 0x4a3c040 is 0 bytes inside a block of size 4 free'd
==28804== at 0x4840D7B: realloc (vg_replace_malloc.c:834)
==28804== by 0x1091FA: dynamCat (dynamCat.c:11)
==28804== by 0x1092D6: main (dynamCat.c:35)
==28804== Block was alloc'd at
==28804== at 0x483E77F: malloc (vg_replace_malloc.c:307)
==28804== by 0x10926D: main (dynamCat.c:26)
==28804==
==28804== Invalid free() / delete / delete[] / realloc()
==28804== at 0x483F9AB: free (vg_replace_malloc.c:538)
==28804== by 0x109312: main (dynamCat.c:41)
==28804== Address 0x4a3c040 is 0 bytes inside a block of size 4 free'd
==28804== at 0x4840D7B: realloc (vg_replace_malloc.c:834)
==28804== by 0x1091FA: dynamCat (dynamCat.c:11)
==28804== by 0x1092D6: main (dynamCat.c:35)
==28804== Block was alloc'd at
==28804== at 0x483E77F: malloc (vg_replace_malloc.c:307)
==28804== by 0x10926D: main (dynamCat.c:26)
==28804==
==28804==
==28804== HEAP SUMMARY:
==28804== in use at exit: 7 bytes in 1 blocks
==28804== total heap usage: 4 allocs, 4 frees, 4,111 bytes allocated
==28804==
==28804== 7 bytes in 1 blocks are definitely lost in loss record 1 of 1
==28804== at 0x4840D7B: realloc (vg_replace_malloc.c:834)
==28804== by 0x1091FA: dynamCat (dynamCat.c:11)
==28804== by 0x1092D6: main (dynamCat.c:35)
==28804==
==28804== LEAK SUMMARY:
==28804== definitely lost: 7 bytes in 1 blocks
==28804== indirectly lost: 0 bytes in 0 blocks
==28804== possibly lost: 0 bytes in 0 blocks
==28804== still reachable: 0 bytes in 0 blocks
==28804== suppressed: 0 bytes in 0 blocks
==28804==
==28804== For lists of detected and suppressed errors, rerun with: -s
==28804== ERROR SUMMARY: 9 errors from 6 contexts (suppressed: 0 from 0)
thank you so much for your help.非常感谢你的帮助。 I am still very new to C and really appreciate your help.我对 C 还是很陌生,非常感谢您的帮助。
If realloc
returns a null pointer, do not free its return value;如果realloc
返回一个 null 指针,不要释放它的返回值; there is no point in passing a null pointer to free
:将 null 指针传递给free
是没有意义的:
char *tmp = realloc(dest, len);
if(tmp == NULL){
fprintf(stderr, "strAppend: realloc messed up\n");
free(tmp); // This does nothing.
dest
is a parameter, so assigning to it changes only the parameter. dest
是一个参数,因此分配给它只会更改参数。 It does not change the original argument:它不会改变原来的论点:
dest = tmp; // This changes only the dest inside dynamCat.
To give the caller a new address, you must either return it as a pointer:要给调用者一个新地址,您必须将其作为指针返回:
char *dynamCat(char *dest, const char *src)
{
…
dest = something;
…
return dest;
}
or you must put it into a pointer passed by the caller:或者您必须将其放入调用者传递的指针中:
void dynamCat(char **dest, const char *src)
{
…
char *tmp = realloc(*dest, len);
…
*dest = tmp;
}
strcat(*dest, src);
}
In the latter case, when calling dynamCat
, you must pass it the address of a pointer:在后一种情况下,当调用dynamCat
时,您必须将指针的地址传递给它:
dynamCat(&one, two);
In the former case, you must take the new pointer from the return value of dynamCat
:在前一种情况下,您必须从dynamCat
的返回值中获取新指针:
one = dynamCat(one, two);
The realloc
function can change the address of the object. realloc
function 可以改变 object 的地址。 When he object is being made bigger, the need for this is obvious: there may not be space at the original location.当他把 object 做得更大时,这样做的必要性是显而易见的:原来的位置可能没有空间。 It's potentially true when shrinking the object also.缩小 object 时也可能是这样。
In abstract terms, when we call realloc(x, newsize)
, the pointer x
becomes indeterminate.抽象地说,当我们调用realloc(x, newsize)
时,指针x
变得不确定。 We must capture the returned pointer y = realloc(x, newsize)
and then use that in all places that previously referred to x
.我们必须捕获返回的指针y = realloc(x, newsize)
,然后在之前提到x
的所有地方使用它。
In your program the catenating function returns void
, and main
keeps referring to the old string.在您的程序中,连接 function 返回void
,并且main
继续引用旧字符串。
Your dynamCat
should be like this:你的dynamCat
应该是这样的:
/* dest is destroyed: use the return value
* in place of dest!
*/
char *dynamCat(char *dest, const char *src) {
size_t len = strlen(dest) + strlen(src) + 1;
printf("strLen: %ld\n", len);
char *tmp = realloc(dest, len);
if(tmp == NULL){
fprintf(stderr, "strAppend: realloc messed up\n");
/* better handling needed here, too */
}
strcat(tmp, src);
return tmp;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.