【发布时间】:2020-10-29 13:18:46
【问题描述】:
我知道人们一直告诉我要阅读文档,但我还没有掌握窍门。我不知道要在文档中查找什么。如果您有关于如何习惯阅读文档的提示,请给我您的提示作为奖励,但现在这是我的问题。在一个简单的程序中说,如果我们 allocate 一些内存块,我可以在完成后 free 它,对吗?这是一个这样的程序,它什么都不做,只是堆中的allocates 和deallocates 内存。
#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);
}
在这里,在我释放它之前,我将地址加一,然后一切都崩溃了。 Free 现在似乎没有分配这块内存(即使它是已分配内存的子集)。如果您想查看它,这是我的错误消息。
*** Error in `./a.out': free(): invalid pointer: 0x0000000001e00011 ***
Aborted (core dumped).
所以这让我开始思考。
- c 是否跟踪在堆上分配的内存
- 如果不是,它怎么知道什么可以释放,什么不可以?
- 如果它有这样的知识,为什么c在退出之前不自动
deallocate这样的记忆。为什么内存泄漏?
【问题讨论】:
-
标题中问题的答案是否定的
-
您只能释放从
malloc等返回的内存。用其他任何东西调用 free 是未定义的行为。 -
您的底线问题的答案是:1. 没有。 2. 没有。这是程序员的责任。 3.“它”没有“这样的知识”。虽然可以实现一个内存管理的基础设施(语言、VM 等)来防止内存泄漏,但这并不是 C 语言标准所指定的。有一些基于 C++之上构建的设计模式可以处理这些问题。您也可以在 C 中实现这些设计模式,尽管这不是在公园里散步。还有像 Java 这样的高级语言,它们使用垃圾收集来处理所有这些。
-
这与 C 无关。这通常是操作系统的责任。如果您想知道它是如何在幕后实现的,那么AFAIK,在大多数情况下,当您在堆上分配一块内存时,操作系统实际上会在该块的开头分配几个字节,它存储长度该块和指向长度块的指针。所以本质上,堆或多或少是作为一个链表来管理的。当您通过地址(指针)删除块时,操作系统会从该地址之前的几个字节中获取元数据。
-
我不理解反对票(以及缺乏更多赞成票):这个问题提出的很好,并显示了研究。 +1