【发布时间】:2010-09-29 14:44:24
【问题描述】:
我在循环中做了类似的事情:
char* test = "\0";
test = strcat(test, somestr);
...
char* tmp = strstr(test, 0, len);
free(test);
test = tmp;
并获得内存泄漏。我做错了什么?
【问题讨论】:
-
why does this code crash? 的可能重复项
我在循环中做了类似的事情:
char* test = "\0";
test = strcat(test, somestr);
...
char* tmp = strstr(test, 0, len);
free(test);
test = tmp;
并获得内存泄漏。我做错了什么?
【问题讨论】:
您实际上并没有内存泄漏(无论如何在您发布的代码中),但是您做错了几件事。
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 中的某处有四个字节(3 个字母 + \0 终止符字节),您可以通过知道它在 RAM 字节数组中的索引来访问该区域.可能还有其他东西存储在您的字符串旁边(例如{ ..., 4, 2, 'f', 'o', 'o', 0, 99, 3, 2, ...}),因此您必须尝试确保您留在该内存空间内,而不会徘徊在相邻的数据中。
【讨论】:
有几个问题:
strcat 会将字符串附加到目标缓冲区。您需要第一个参数是缓冲区而不是字符串文字指针。这是一个字符缓冲区的示例,也称为字符数组:char test[1024];
strcat 的返回值是一个指向目标缓冲区的指针,它不是堆上新分配的字符串。所以你不应该在返回值上调用free。
【讨论】:
您不能将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 函数。
记住。 99.9% 的情况下,每个 malloc 分配都会有一个 free 调用。
【讨论】: