c 是否跟踪分配的堆内存?

Does c keep track of allocated heap memory?

我知道人们一直告诉我要阅读文档,但我还没有掌握要领。我不知道在文档中寻找什么。如果您有关于如何习惯阅读文档的提示,请给我您的提示作为奖励,但现在这是我的问题。在一个简单的程序中说,如果我们 allocate 一些内存块,我可以 free 一旦完成,对吧?这是一个这样的程序,它什么都不做,但堆中有 allocatesdeallocates 内存。

#include <stdio.h>
#include <stdlib.h>


int main(void)
{
char *s = malloc(10);
free(s);
return (0);
}

编译后,如果我们运行 valgrind 我们可以看到所有东西都被释放了。现在,这里只是对之前程序的一点改动。

#include <stdio.h>
#include <stdlib.h>


int main(void)
{
char *s = malloc(10);
s++;
free(s);
return (0);
}

在这里,在我释放它之前,我将地址递增 1,一切都乱套了。 Free 现在似乎没有分配这块内存 (即使它是已分配内存的子集)。如果您想查看它,这是我的错误消息。

*** Error in `./a.out': free(): invalid pointer: 0x0000000001e00011 ***
Aborted (core dumped). 

所以这让我开始思考。

  1. c 是否跟踪堆上分配的内存
  2. 如果不是,它怎么知道什么该释放什么不该释放?
  3. 如果它有这样的知识,为什么 c 在退出之前不会自动 deallocate 这样的记忆。为什么内存泄漏?

free 的 C 标准描述如下:

  1. The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

由于您更改了指针,它与内存管理函数返回的指针不匹配(即m/re/calloc),行为是未定义,任何东西都可以发生。包括注意到您已尝试释放无效指针的运行时库,但运行时也不需要这样做。


至于

  1. Does C keep track of memory's allocated on the heap

可能……但不一定……

  1. If not, how does it know what to free and what to not?

好吧,如果它确实释放了指针指向的内存,那么它显然需要对分配的大小进行某种簿记......但它不需要能够弄清楚是否所有指针仍指向该内存区域。

  1. And if it has such a knowledge, why doesn't c automatically deallocate such memories just before exiting. why memory leaks?

通常是操作系统在进程退出后释放内存。那不是问题。真正的问题是程序 仍然 运行.

时发生的泄漏

我的知识有限。但我想我可以解决你的一些问题

  1. Does c keep track of memory's allocated on the heap

C 不跟踪任何内容。然而,OS 会跟踪并知道哪些内存区域已被使用,哪些未被使用。

  1. If not, how does it know what to free and what to not?

how-does-free-know-how-much-to-free
简单地说。当调用 malloc 时,你给它一个大小。 malloc 在指针 returns 前面使用 额外的 8 个字节 来“记住”这个大小信息。当你free说指针的时候,free会知道地址,读取指针前8个字节得到大小信息,然后愉快的释放内存给操作系统。

  1. And if it has such a knowledge, why doesn't c automatically deallocate such memories just before exiting. why memory leaks?

OS知道的信息。因此,当 C 程序退出时,OS 将负责并释放您未明确释放的内存。

*** Error in ./a.out': free(): invalid pointer: 0x0000000001e00011 *** Aborted (core dumped).`

至于这个。我给出了 glibc free 函数的片段
glibc malloc 将以对齐模式分配内存区域,比如 32 字节对齐。因此,当您执行 s++ 时,它不再是 32 字节对齐的。
现在你可能会想,如果我做 s += 32; 并在 s 之前设置一个假装的尺寸信息会怎样。我试过了。遗憾的是我不能天真地欺骗 glibc 的 free 函数。它还有其他信息可以防止这种情况发生。我现在停下来深入研究...