【问题标题】:Is it possible to force Linux to invalidate virtual memory after free是否可以强制Linux在释放后使虚拟内存无效
【发布时间】:2013-10-17 15:16:54
【问题描述】:

在 Windows 上,我注意到尝试取消引用指向最近释放的内存的指针会导致崩溃,并被 Visual Studio 捕获,指出内存无效。这正如预期的那样。但是,执行相同的应用程序和代码路径导致取消引用指向最近释放的内存的指针不会立即导致 Linux 崩溃。这向我表明,Linux 内核(或 GNU C++ 运行时)不会很快使释放的内存失效,即使在调试版本中也是如此。应用程序需要更长的时间才能崩溃。是这样吗?如果是这样,我可以强制内存更快地取消映射吗?如果不是,那是怎么回事?

【问题讨论】:

  • 我不知道。每当出现这种情况时,我都会停止进行 UB,而不是尝试准确了解正在发生的事情。

标签: c++ c linux windows virtual-memory


【解决方案1】:

你试过http://valgrind.org/吗?其目的是帮助追查您所描述的问题。

【讨论】:

  • +1;瓦尔格林德很棒。也许复杂得可笑,但它是一个极好的工具。
  • 是的,我正在使用 Valrgind。 memcheck 工具清楚地报告从无效内存读取。我只是对 Windows 和 Linux 对释放内存的处理方式之间的明显区别感到好奇。
  • 嗯,AFAIK 行为没有定义,所以难怪它在不同系统(甚至编译器、编译器版本、编译器选项)上会有所不同。
【解决方案2】:

new/delete 的大多数实现不返回内存 立即到系统,或者至少不要返回更小 块。我很惊讶您的代码在 Windows 只需取消引用指向内存的指针即可;你是 确保您没有做更多的事情(例如,使用您读取的值 通过指针)。

块有多大?许多实现使用不同的 策略取决于块的大小,并且会释放 非常大的块立即。 (IIRC,Linux 会做一个mmap 对于非常大的块,立即取消映射,当 你释放它。当然,如果你在 释放并取消引用指针,有可能 地址在新分配的空间中,不会崩溃。)

最后:映射的粒度是页面,而你 不能指望分配器为每个分配器阻塞一个完整的页面 分配,只是为了使内存无效 立即解除分配。 (一页大概至少4K, 并且您不想每次都丢失 4K 地址空间 分配 16 个字节。)缺少跟踪所有内存访问(例如 ValGrand 或 Purify),并且运行速度慢很多,唯一的 另一种方法是使用垃圾收集,以确保 只要有指向它的指针,就不会重新分配内存, 并在释放时完全覆盖它(即在deletefree) 的值如果使用可能会导致问题 (0xDEADBEEF,或类似的东西)。即便如此,你还是 不能保证你会崩溃—0xDEADBEEF 可以 是您认为正在阅读的内容的有效值。 (但是这个 确实允许例如在构造函数中设置一个标志,重置它 在析构函数中,并在每个函数中对其进行测试。对于代码 必须积极防御。)

【讨论】:

    猜你喜欢
    • 2020-02-19
    • 1970-01-01
    • 2011-02-27
    • 1970-01-01
    • 2011-01-12
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多