【问题标题】:free Memory in cc中的空闲内存
【发布时间】:2012-09-18 00:57:24
【问题描述】:

我有疑问:

void *a = malloc(40);
free(a);

如果我认为 malloc(40) 分配了 40 个字节的内存并返回该内存的地址,然后 free(a) 取消分配/释放该内存 但对驻留在其中的位模式不做任何事情记忆。所以,假设这块内存被分配为 void *b,然后在打印 b 指向的地址处的值时,会得到与原来相同的值,或者它给了我一个垃圾值,为什么?

【问题讨论】:

  • 这不是“怀疑”。这是一个问题。 SO 是一个问答网站,而不是怀疑论者的博客。
  • @KerrekSB:我什至没有注意到“怀疑”部分,我习惯于与印度的人发电子邮件,他们的疑问将尽快得到澄清...... :-}
  • @FrerichRaabe:我已经注意到这一点很长时间了,但这对我来说从来没有意义......你可以怀疑耶稣(如果你的名字是托马斯),但你可以'不要怀疑malloc
  • @FrerichRaabe 虽然我知道你来自哪里,但我必须同意 Kerrek 的观点,这一直是我的烦恼
  • @KerrekSB:我的意思是我有一个问题。如果伤害了你我很抱歉:P

标签: c memory malloc


【解决方案1】:

我假设您已经想到了这种情况:

void * a = malloc(40);
free(a);
void * b = malloc(40);

assert(a == b);

这当然是完全合理的,因为内存可能会被重用。

但是,自从a == b 以来,您已经回答了自己的问题:b 的值与a 的值相同!

我相信您问错了问题,并且您实际上有兴趣比较b 指向的内存。那是一锅完全不同的鱼。在两个malloc 调用之间可能发生任何事情。没有什么是保证的。 malloc 调用的返回值指向的内存是未初始化的,您不能对其内容做出任何假设。按理说,在典型的优化 C 库中内存不会发生变化,但不能保证。 “安全”的运行时环境可能会选择使用特定的测试模式覆盖已释放或分配的内存,以便更好地检测无效访问。

【讨论】:

  • 即使没有一个“安全”的运行时来写一个特定的值,发明一个使用每个空闲块的前几个字节的内存分配器并不是很困难。自己的家政信息。不过,通常分配块的内务管理使用的空间不会比空闲块少。
【解决方案2】:

它可以为您带来任何价值。
C/C++ 标准不要求值是任何特定的。用技术术语来说,任何未初始化的变量/内存的值都是Indeterminate

简而言之,你的程序不应该依赖这个值来做任何具体的事情,如果是,那么它就是不可移植的。

【讨论】:

    【解决方案3】:

    它不能保证任何事情。您从 ma​​lloc 获得的打印块可能会打印以前的数据,也可能不会。有很多事情可以改变下一个 malloc 块(因此下一个地址会不同)或改变旧的内存块本身。

    【讨论】:

      【解决方案4】:

      free 通常会修改你正在释放的内存。

      这是一个常见的技巧,尤其是在调试模式下,使用某些固定模式覆盖内存,以便更容易判断您是在双重释放内存,还是只是在操作释放的内存。

      同样,malloc 可能会用不同的模式覆盖内存,以使内存明显未初始化。

      【讨论】:

        【解决方案5】:

        malloc 和 free 是 C 风格的内存管理,而不是 C++。 C++ 的替代品是 new 和 delete 运算符。至于 free() 后内存中剩余的位模式,是的,它是相同的位模式。如果你想手动删除位模式,你可以使用 memset() 或 ZeroMemory() 如果你编写 WinApi 代码。

        【讨论】:

          【解决方案6】:

          它会给你一些垃圾值,因为函数 free() 会将指定的字节设置为某种模式,这将使内存知道这些字节被释放和未初始化。话虽如此,您遇到问题中定义的案例的可能性很小且极不可能。即使您将再次获得相同的字节,相信我,您也不会认出它们:-)

          AFAIK,free() 通常将内存设置为 0xFE 0xEE with Visual Studio,这大致意味着内存已分配但现在已释放。这些值被称为 Sentinel Values,这意味着堆仍归进程所有,但未使用。从进程中释放的内存会显示“?? ??”

          【讨论】:

            【解决方案7】:

            首先,代码不是c++,而是纯c。

            原因是,free() / delete 存在,因此系统可以注意内存区域再次可供分配。

            它为什么要做更多的事情?

            但是,这是一个安全问题。我相信一些面向安全的现代系统在将内存分配给应用程序之前会将其归零。然后,如果您第一次使用malloc(),您将获得与calloc 等效的值。无论如何,如果您碰巧释放内存然后再次分配它可能能够读取您自己的数据。

            这种行为的原因很简单。将内存归零会很耗时,您可以手动完成。实际上它有O(n) 的复杂性。如果您编写一个重用其内存的数字运算器,那么您不在乎在malloc() 之后得到什么,因为您很可能应该覆盖它,并且您绝对不希望您的 FLOPS 受到不必要的memset() 的负面影响致电free()

            如果您想确保在调用free 之后没有任何东西可以读取内存,您需要在调用free() 之前使用memset(a, 0, SIZE)

            【讨论】:

              猜你喜欢
              • 2015-03-21
              • 2018-06-06
              • 1970-01-01
              • 2018-08-21
              • 2015-04-29
              • 2015-08-17
              • 1970-01-01
              • 1970-01-01
              • 2021-12-12
              相关资源
              最近更新 更多