正如标题所暗示的那样,我是C的新手并且很快就会出现中期。我正在修改过去的论文,一个反复出现的主题是双重免费问题。我知道这是在同一个内存位置上调用free()
两次的过程,但我有几个问题,我不是100%肯定如何回答:
问题1:C中双重免费的结果是什么,为什么会出现这样的问题?
这将导致双重免费:
char* ptr = malloc(sizeof(char));
*ptr = 'a';
free(ptr);
free(ptr);
我对此的回应是,它会返回0x0内存地址并导致系统不稳定/崩溃。另外,如果我没记错的话,双重自由实际上可以调用malloc
两次,这会导致缓冲区溢出,从而使系统容易受到攻击。
简要总结这个问题的最佳方式是什么?
问题2:描述一种特别容易引入的情况 C中双倍免费?
我在想当你绕过指针时可能会意外地将它释放到一个函数中,并且在没有意识到的情况下再次释放它?
再次,总结这个的“最佳”方式是什么?
答案 0 :(得分:22)
从技术上讲,C中的双重免费会导致未定义的行为。这意味着该程序可以完全随意地运行,所有投注都不会发生。发生这当然是一件坏事!实际上,双重释放内存块会破坏内存管理器的状态,这可能会导致现有的内存块被破坏,或者将来的分配以奇怪的方式失败(例如,相同的内存分配给两个malloc
)的不同连续调用。
双重自由可能发生在各种情况下。一个相当常见的问题是,当多个不同的对象都有指向彼此的指针并开始通过调用free
进行清理时。发生这种情况时,如果您不小心,清理对象时可能会多次free
同一指针。不过,还有很多其他案例。
希望这有帮助!
答案 1 :(得分:5)
因为free()将通过在每个区域之前管理存储在标签中的信息来合并相邻区域。这就像管理双链表一样。因此,如果ptr
所指向的缓冲区已被攻击字符串覆盖,则可能会被注入伪标记。
答案 2 :(得分:2)
这个问题已经得到了很好的解答,但由于重复的问题,我添加了一个迟到的答案"链接,询问"如何避免它?"
在发布的示例代码中添加了一行。
char* ptr = malloc(sizeof(char));
*ptr = 'a';
free(ptr);
ptr = NULL; // add this
free(ptr);
函数free
对NULL
指针不执行任何操作。
答案 3 :(得分:0)
根据已发布的C11标准,在已free
内存位置调用free
会导致未定义的行为。它可能导致奇怪的情况,例如内存即使在可用时也没有被分配,堆被破坏,相同的内存位置被分配给不同的mallocs等。基本上,它是未定义的,可以是任何东西。
ANSI C11标准可以在这里找到。 https://www.iso.org/obp/ui/#iso:std:iso-iec:9899:ed-3:v1:en
编辑:根据评论将NULL更改为已free
d。此外,链接现在指向ISO / IEC 9899:2011(en)