46

正如标题所暗示的那样,我是 C 的新手,很快就会有期中考试。我目前正在修改过去的论文,一个反复出现的主题是双重免费问题。我知道这是free()两次调用同一内存位置的过程,但我有几个问题我不是 100% 确定如何回答:

问题 1:C 中 double free 的结果是什么,为什么会出现这样的问题?

这将导致双重释放:

char* ptr = malloc(sizeof(char));

*ptr = 'a';
free(ptr);
free(ptr);

我对此的回应是它会返回一个 0x0 内存地址并导致系统不稳定/崩溃。另外,如果我没记错的话,双重释放实际上可以调用malloc两次,这会导致缓冲区溢出,从而使系统易受攻击。

简要总结这个问题的最佳方式是什么?

问题 2:描述一个特别容易在 C 中引入 double free 的情况?

我在想当你在你周围传递指针时可能会不小心在一个函数中释放它,并且在没有意识到的情况下再次释放它?

同样,总结这一点的“最佳”方式是什么?

4

4 回答 4

52

从技术上讲,C 中的双重释放会导致未定义的行为。这意味着该程序可以完全任意地运行,并且所有关于发生的事情的赌注都没有。这肯定是一件坏事!在实践中,双重释放内存块会破坏内存管理器的状态,这可能会导致现有内存块损坏或未来分配以奇怪的方式失败(例如,相同的内存分配给两个的不同连续调用malloc)。

在各种情况下都可能发生双重释放。一种相当常见的情况是,当多个不同的对象都具有彼此的指针并开始通过调用free. 发生这种情况时,如果您不小心,可能会free在清理对象时多次使用同一个指针。不过,还有很多其他情况。

希望这可以帮助!

于 2014-01-11T01:43:36.867 回答
12

因为 free() 将通过管理存储在每个区域之前的标签中的信息来合并相邻区域。这有点像管理双链表。因此,如果ptr指向的缓冲区已被攻击字符串覆盖,那将是危险的,其中可以注入虚假标签。

于 2017-10-16T20:46:06.587 回答
7

这个问题已经得到很好的回答,但由于“重复问题”链接,我添加了一个较晚的答案,该链接询问“如何避免它?”

在发布的示例代码中添加了一行。

char* ptr = malloc(sizeof(char));

*ptr = 'a';
free(ptr);
ptr = NULL;         // add this
free(ptr);

函数对指针free不做任何事情。NULL

于 2018-06-10T17:52:13.687 回答
4

根据已发布的 C11 标准,调用free已经存在的free内存位置会导致未定义的行为。它可能导致奇怪的情况,例如即使内存可用,也没有分配内存,堆损坏,相同的内存位置分配给不同的 malloc 等。基本上,它是未定义的,可以是任何东西。

可以在这里找到 ANSI C11 标准。https://www.iso.org/obp/ui/#iso:std:iso-iec:9899:ed-3:v1:en

free编辑:根据评论将 NULL 更改为已经d。此外,链接现在指向 ISO/IEC 9899:2011(en)

于 2015-12-24T14:56:26.880 回答