我正在编写一个动态分配的C程序
有人可以在“ goto”中解释如何解决此内存泄漏
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
int main()
{
printf("start main\n");
char *f = NULL;
L1:
f = (char *)malloc(10);
if (f == NULL)
return -1;
printf("body lebel\n");
f = "A";
if (f == "B") {
free(f);
goto L1;
}
return 0;
return 0;
}
valgrind --leak-check=full ./a.out
,
输出:
==7217== HEAP SUMMARY:
==7217== in use at exit: 10 bytes in 1 blocks
==7217== total heap usage: 2 allocs, 1 frees, 1,034 bytes
allocated
答案 0 :(得分:1)
第一
f = "A";
将char指针f
分配为指向"A"
,这是一个const char*
,位于过程映像中的某个位置。这将完全孤立您用malloc
分配的内存。要将字符串"A"
复制到f
指向的内存中,您需要编写类似
strcpy(f, "A");
或
strncpy(f, "A", 10);
警告:strcpy
可能会超出您为f
分配的缓冲区,而strncpy
可能会使其保留为非空值。
第二,您只能在if语句内释放f
,然后再跳至L1
。要在程序退出之前也释放f
,还必须在free(f)
之前写return 0
。
第三,f == "B"
检查f
是否指向const char *值"B"
,而不是其内容是否与"B"
相同。在您的程序中,这始终是错误的,因为您在比较之前就将其分配给了"A"
。您需要将strcmp
之类的函数用于以null终止的字符串,或者将memcmp
用于可能以非null终止的字符串。
还可以将第一个free
移动到标签的开头,这样就不必确保在跳转之前将其释放,因为free(NULL)
不会这样做任何东西。同样出于后代的利益,您应该将"A"
和"B"
声明为变量,并将常量10
移动到变量中,以防止将来发生内存冲突:
int main()
{
const char a_str[] = "A";
const char b_str[] = "B";
size_t buffer_size = 10;
printf("start main\n");
char *f = NULL;
L1:
free(f);
f = (char *)malloc(buffer_size);
if (f == NULL)
return -1;
printf("body lebel\n");
if (buffer_size < sizeof(a_str)) {
printf("Buffer too small for %s\n", a_str);
exit(1);
}
memcpy(f, a_str, sizeof(a_str));
if (buffer_size < sizeof(b_str)) {
printf("Buffer too small for comparison with %s\n", b_str);
exit(1);
}
if (!memcmp(f, b_str, sizeof(b_str)) {
goto L1;
}
free(f);
return 0;
}