我在循环中做了类似的事情:
char* test = "\0";
test = strcat(test, somestr);
...
char* tmp = strstr(test, 0, len);
free(test);
test = tmp;
并获得内存泄漏。我做错了什么?
答案 0 :(得分:3)
你实际上没有内存泄漏(在你发布的代码中),但你做错了几件事。
char* test = "\0";
这声明了一个名为 test 的指针,并将其初始化为指向一些两个字节的文字数组{0,0}
test = strcat(test, somestr);
这会尝试将某些内容附加到该字符串文字的末尾(因为作为C字符串,它是空的,就像字符串副本一样)。文字值通常存储在不可写的内存中,因此将内容复制到此内存中可能会导致错误(许多操作系统上出现分段错误或SIGSEGV)。此外, test 只指向两个字节的存储空间,这意味着除非 somestr 指的是 strlen 小于或等于的字符串到1你最终会尝试写一些其他内存(无论发生在 test 指向的“\ 0”之后)。
char* tmp = strstr(test, 0, len);
我不知道这里发生了什么,因为 strstr 只需要2个参数(两者都是const char *
)。
free(test);
在这里,您尝试释放非堆分配的内存。堆是malloc,realloc和calloc获取它们分配的内存的地方。使用其中一个函数(以及某些系统上的一些其他函数)未返回的内存位置调用 free 是一个错误,因为 free 不知道该怎么做和他们一起。
你应该记住,通常内存是巨大的字节数组,你使用的指针就像数组索引。您正在使用的系统可能能够区分此阵列的某些区域并确定如何访问它们(可读,可写和/或可执行)。但它仍然只是一个字节数组。当你有一个字符串(例如"foo"
)意味着RAM中的某个地方有4个字节(3个字母+ \ 0终结符字节),你可以通过知道它在字节数组中的索引来访问这个区域是RAM。可能还有其他东西存储在您的字符串旁边(例如{ ..., 4, 2, 'f', 'o', 'o', 0, 99, 3, 2, ...}
),因此您必须尝试确保您保持在该内存的空间内而不会徘徊到相邻数据中。
答案 1 :(得分:1)
有几个问题:
strcat
会将字符串附加到目标缓冲区。您需要第一个参数是缓冲区而不是字符串文字指针。以下是char缓冲区的示例,也称为chars数组:char test[1024];
strcat
的返回值是指向目标缓冲区的指针,它不是堆上新分配的字符串。因此,您不应在返回值上调用free
。
答案 2 :(得分:1)
您不能strcat
到test
,因为您最初将其指向常量char *
。你需要为它分配内存。 strcat
不会这样做。
将您的代码更改为:
char* test = (char*)malloc(20*sizeof(char));
test[0] = '\0'; // nothing on this string to begin with
strcat(test, "something");
free(test);
此外,这不起作用:
char* tmp = strcat(test, 0, len);
由于没有带有三个参数的strcat
函数。
记住。每次free
分配时,有99.9%的时间会有malloc
次来电。