我有这段代码片段来理解C中的内存管理函数void free(void*)
。我对free
函数的了解是它将释放由指针管理的内存。我希望看到在内存块被释放后会发生什么和是否仍然可以访问该内存块关联的指针。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR_SIZE 20
int main(int argc, char *argv[])
{
char originalChar [] = "123456789";
char *myChar = (char*) malloc(sizeof(char) * STR_SIZE);
if (!myChar) {
printf("allocation failed!");
exit(1);
}
char *isOk = strncpy(myChar, originalChar, STR_SIZE*sizeof(char));
if(!isOk) exit(1);
char *myCharCopy = myChar;
printf("oC = %d, mCC = %d; mC = %d\n", originalChar, myCharCopy, myChar);
printf("The strings = %s\n", myChar);
printf("The strings = %s\n", myCharCopy);
free(myChar);
printf("----- free happened here -----\n");
// myChar = NULL;
printf("oC = %d, mCC = %d; mC = %d\n", originalChar, myCharCopy, myChar);
printf("The strings = %s\n", myChar);
printf("The strings = %s\n", myCharCopy);
return 0;
}
然后,我从输出中得到了这些结果。
oC = 1482066590, mCC = 826278544; mC = 826278544
The strings = 123456789
The strings = 123456789
----- free happened here -----
oC = 1482066590, mCC = 826278544; mC = 826278544
The strings = 123456789
The strings = 123456789
这个结果对我来说没什么意义。因为free
函数应该释放内存块,但结果是 NOT 。到底发生了什么?此外,似乎与堆上的内存关联的指针仍然可以被释放的内存访问。为什么会这样,因为它被释放了?
答案 0 :(得分:3)
根据C11
标准,章节§7.22.3.3, free
函数
free
函数导致ptr
指向的空间被释放,即 可供进一步分配。[..]
它并不强制将指针设置为NULL(或其他任何东西)。 free()
- 仅仅是操作系统的指示,可以在需要时回收和重新发布已分配的内存。
访问free()
- d内存为undefined behavior。因此,一旦调用free()
,就不应再访问指针了。
由于这个原因,在调用free()
之后立即将free()
- d指针设置为NULL通常被认为是一种好习惯,以避免对已释放的内存进行任何意外访问。
那就是说,
printf("oC = %d, mCC = %d; mC = %d\n", originalChar, myCharCopy, myChar);
也会调用undefined behavior。 %d
是打印int
,而不是指针(或字符串)。如果您想打印地址,可能需要使用
printf("oC = %p, mCC = %p; mC = %p\n", (void*)originalChar, (void*)myCharCopy, (void*)myChar);
答案 1 :(得分:2)
根据C standard:
7.22.3.3
free
功能...
free
函数会导致ptr
指向的空间 取消分配,即可用于进一步分配。如果ptr
是一个空指针,不会发生任何操作。否则,如果参数确实如此 与先前由内存管理函数返回的指针不匹配, 或者如果通过调用free
或realloc
释放了空格,则行为未定义。
但现在你的代码再次按照C标准访问内存,调用未定义的行为:
J.2未定义的行为
1在以下情况下,行为未定义:
...
指向通过调用释放的空间的指针的值 使用
free
或realloc
函数(7.22.3)。
包括出现“工作”。