如何为局部变量释放动态分配的内存?



示例程序:

#include <stdio.h>
#include <malloc.h>
void f(int n) {
char *val = (char *) malloc(12*sizeof(char));
val = "feels....";
printf("%s", val);
//  free val;     // if enable, compile time error: expected ';' before 'val'   free val;   
}
int main()
{
f(1);
return 0;
}

是否需要释放动态分配的内存?如果是,如何释放。

是的,您需要释放内存。但是,当您为字符串分配内存时,填充字符串的方法不是为其分配字符串,因为这会替换您分配的内存。相反,你打算像这样使用函数strcpy......

char *val = malloc(12*sizeof(char));
strcpy(val,"feels....");
printf("%s", val);
free(val);

取而代之的是:

char *val = (char *) malloc(12*sizeof(char));
val = "feels....";  // val points now to the string literal ""feels...."
// discarding the value returned by malloc
...
free(val);          // attempt to free the string literal which will
// result in undefined behaviour (most likely a crash)

你可能想要这个:

char *val = malloc(12*sizeof(char));  // in C you don't cast the return value of malloc
strcpy(val, "feels....");  // the string "feels...." will be copied into
// the allocated buffer
...
free(val);          // free memory returned previously by malloc

编译问题是因为free是一个函数,你需要把它的参数放在括号里。

free(val);

另一个问题是内存泄漏。

C 中的字符串实际上只是指向(希望(包含char数据的内存块的指针。字符串的末尾由值为 0 的char表示。要记住的是,您的变量只是像任何其他指针一样的指针。所以。。。

char *val = (char *) malloc(12*sizeof(char));

上行动态分配内存块,并将指向该内存块的指针分配给val

val = "feels....";

上面的行分配了一个指向字符串文本的指针,以val覆盖val中的上一个指针。它没有以任何方式触及在第一行中malloc的内存块。此外,您已经丢失了对malloced块的任何引用,因此它已泄漏。没有办法free它。

字符串文字通常在编译时创建,它们占用的内存将成为程序的一部分。这意味着它们不是来自堆(malloc从那里获取内存。这意味着,反过来,当您尝试free字符串文字时,会发生不好的事情。在现代体系结构上,程序文本受到操作系统级别的写入保护,因此尝试free其中的一部分几乎肯定会使程序崩溃。

只要您不想更改字符串的内容,就不需要为其malloc空间。您可以省略malloc行(以及相应的free(,您的程序仍然可以工作。

如果您确实想更改字符串,获取字符串文本的可变副本的最简单方法是使用strdup

char *val = strdup("feels....");
// Do stuff with the string
free(val); // strdup strings need to be freed

strdup是一个 Posix 函数,但不是 C 标准函数,因此您的平台可能没有它。不过,实现自己的非常简单。

char* myStrDup(const char* thingToDup)
{
char* ret = malloc(strlen(thingToDup) + 1); // strlen returns the length without the terminating nul. Hence add 1 to it to allocate
strcpy(ret, thingToDup); // Copies the entire string including the terminating nul.
return ret;
}

最新更新