我读了很多关于标准 C 中的 malloc() 和 free() 的内容。据我了解,您malloc()
只为了一次记忆,然后你free()
同样的记忆只有一次。这可能是不好的做法,但我明白,在你之后malloc()
内存,您可以定义多个指向它的指针。而一旦你free()
那些指针中的任何一个,分配的内存被取消分配吗?
考虑这个玩具示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(){
char* p = (char*)malloc(10 * sizeof(char)); // allocate memory
int* q = (int*)p; // pointer to the same block of memory
*p = 'A'; // Input some data
printf("TEST:: %c %d\n", *p, *q); // Everything's ok so far...
free(p); // free() my allocated memory?
sleep(10); // wait
printf("%c\n", *q); // q now points to de-allocated memory
// shouldn't this segfault?
free(q); // *** SEGFAULTS HERE ***
return 0;
}
输出是:
[Linux]$ ./a.out
TEST:: A 65
*** Error in `./a.out': double free or corruption (fasttop): 0x0000000001ac4010 ***
======= Backtrace: =========
...lots of backtrack info...
所以我假设当我free()
第一个指针,考虑内存free()
编辑,但是数据值我在这块内存中写的仍然“在那里”,这就是为什么我可以通过第二个指针访问它们?
(我并不是说这是一个好主意,我只是想理解系统的逻辑。)
当您分配内存时,您将获得一个指向某个空间的指针,当您释放它时,您将其返回给系统。通常,您仍然可以访问该内存,但在释放内存后使用它是非常糟糕的。
确切的行为是未定义的,但在大多数系统上,您可以继续访问内存,或者出现段错误。
您可以尝试的一个有趣的实验是在释放该指针后尝试分配更多内存。在我尝试过的大多数系统上,您都会得到相同的块(如果您依赖于已释放块中的数据,这是一个问题)。您的程序最终将使用两个指针,但由于它们指向相同的物理数据,因此您将覆盖您自己的数据!
这样做的原因是,当您 malloc 数据时(当然取决于 malloc 实现),malloc 首先从操作系统请求一个数据块(通常比 malloc 请求大得多),然后 malloc 会给您该数据的一部分记忆。不过,您将能够访问最初从操作系统获得的内存 malloc 的任何部分,因为对于操作系统来说,它是您的程序内部使用的所有内存。当您进行释放时,您是在告诉 malloc 系统该内存是空闲的,并且可以稍后返还给程序。
在 malloc 区域之外写入是非常危险的,因为
- 它可能会出现段错误,具体取决于您的 c 实现
- 您可以覆盖 malloc 所依赖的元数据结构,这会在稍后释放/malloc 更多数据时导致非常糟糕的问题
如果您有兴趣了解更多信息,我建议您通过 valgrind(泄漏检测器)运行您的程序,以更好地了解已释放/未释放的内容。
PS:在没有操作系统的系统上,您很可能根本不会出现段错误,并且您可以随心所欲地在任何地方进行写入。操作系统负责触发段错误(当您写入/读取您无权访问的内存时,例如内核或受保护的内存)
如果您有兴趣了解更多信息,您应该尝试编写自己的 malloc,和/或阅读/了解内存管理操作系统的知识。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)