当我调用 free(a)
时到底发生了什么?我知道它正在释放使用的内存,但这是否也意味着存储在数组 a
中的数据无法再访问(因此,无法调用 copyArray
) ?
int *a = (int *) malloc(sizeof(int) * numberOfInts);
for (i = 0; i < numberOfInts; i++) {
a[i] = random();
printf("%d\n", a[i]);
}
free(a);
copyArray(*a++, numberOfInts);
最佳答案
What exactly is happening when I call free(a)?
这是特定于实现的。例如,对于 Linux 和 glibc,可能会发生以下几种情况之一:
如果内存分配在 128k 或更大的 block 中,glibc
将分配一个新的内存区域(具体来说,写时复制 mmap
的 /dev/zero
)。当它被释放时,内存区域被简单地释放(munmap
'd)并消失。进一步的访问将崩溃。
如果分配的内存较小,它将进入堆。堆是从固定地址开始的单个内存区域,其大小可由进程缩小或增加(使用 sbrk
)。
内存分配器跟踪分配了该区域的哪些部分。第一次分配东西时,堆的大小增加,内存被追加到这个新空间的末尾。
如果释放这样的内存块,在堆的末尾,堆的大小可以减小,从而使内存无效并使进一步的访问崩溃。不过,分配器不会增加或减少几个字节的堆大小,因此此时它取决于分配的大小和释放的 block 数。它可能是可访问的,也可能不是。
如果您分配十个内存块并释放前九个,您最终会在堆中得到一个未使用的区域。由于您只能通过设置结束地址来修改堆大小,因此您实际上无能为力。内存仍然有效,访问它仍然有效。您甚至可能会在其中找到您的原始数据,并且能够像什么都没发生一样继续。
但是,随着新内存的分配,malloc
将尝试将其放入这个未使用的区域,从而让其他数据覆盖原来存在的数据。在你的 free'd 数组中设置一个 int 可能会在你的程序的一个完全不相关的部分覆盖一个指针,并且随之而来的是欢闹和调试。
tl;dr:不要访问释放的内存!
关于在 C 中调用 free(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14986543/