【问题标题】:jemalloc not detecting memory corruptionjemalloc 未检测到内存损坏
【发布时间】:2016-10-10 11:37:29
【问题描述】:

以下程序不会触发断言失败:

int main(int argc, char **argv)
{
  int * n = (int *)malloc(100);
  //malloc_stats_print(nullptr, nullptr, "gablh");
  free(n);
  *n += 1;
  std::cerr << *n << std::endl;
  for (int i = 0; i != 10; ++i) {
    std::cerr << *(n+i) << std::endl;
  }
}

当我运行程序时 MALLOC_CONF="quarantine:32,abort:true,stats_print:true" ex_stats_pr

我明白了:

1515870811
1515870811
1515870810
1515870810
1515870810
1515870810
1515870810
1515870810
1515870810
1515870810
1515870810

有没有办法用 jemalloc 触发中止失败?

【问题讨论】:

  • 阿弥陀佛,jemalloc有机会做检查吗?你的程序释放,然后尝试破坏内存,打印一些东西然后退出,而不需要对 jemalloc 进行任何额外的调用。例如,隔离选项应该与 valgrind 一起使用,而不仅仅是在普通运行中(valgrind 可能会做一些检查):linux.die.net/man/3/jemalloc“隔离的内存在从隔离区释放之前不会被释放,...这个功能特别有用与 Valgrind [2] 结合使用,可以检测访问隔离对象的尝试。”

标签: c++ malloc jemalloc


【解决方案1】:

您希望 jemalloc 检测到对已释放内存的一次写入和对已释放内存的一些读取。

但是 jemalloc 库没有这个能力。它的调试模式只检测有限的一组导致内存损坏的错误。例如双释放。

这不是任意限制,因为像 jemalloc 这样的库无法检测到任何类型的内存访问错误。这意味着作为一个库,它可以轻松地重载 malloc()/free() 等并安装退出处理程序。因此,调试模式实现可以有效地实现一组有限的检查。当然,每个调试模式实现都会选择自己的权衡取舍。例如,jemalloc 也不会在空闲期间检测简单的缓冲区溢出,尽管其他具有调试功能的库(例如 Solaris 的libumem)实现了一种轻量级机制,其中检查了一些特殊尾随字节的完整性。

对于像 jemalloc 这样的库来检测对已释放内存的读/写,它必须在每个已释放区域中安装调试器样式的监视程序,这将非常复杂并产生显着的运行时开销 - 如果这可以扩展到许多和大型分配,完全没有。

重点是:jemalloc 是检测写入已释放内存 (A) 和读取已释放内存 (B) 的错误工具。

例如,GCC 和 Clang 附带的Address Sanitizer (-fsanitize=address) 能够检测 (A),但不能检测 (B)。并且Valgrind (valgrind --tool=memcheck) 能够同时检测 (A) 和 (B) 并将这些问题报告为对已释放块的无效读/写。这两种工具肯定比分配器库的简单调试模式具有更高的运行时开销。而且由于 valgrind 的方法是模拟 CPU,它的开销比 Address Sanitizer 的要高得多。

【讨论】:

    【解决方案2】:

    这不是您问题的直接答案,但是...

    未定义的行为是未定义的。玩弄被释放的记忆就属于这个阵营。根据您的内存处理程序的实现,您可能有一个“验证内存”类型的函数,它沿着您的空闲内存列表查看是否存在某种损坏,但即使这样也不会捕获所有内容(不是熟悉jemalloc,尤其是我自己)。可能是您上面的代码碰到了没人关心的内存,因此不会被抓住。哎呀,您的 std::cerr 语句也在执行未定义的行为,因此您甚至不能相信它的值(想想线程和操作系统抓取和更改内存等)

    这是您尽可能不在 C++ 中直接使用指针的原因之一。管理生命周期的智能指针和容器可以自动防止几乎所有这些类型的错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-19
      • 2011-04-07
      • 2011-07-24
      • 1970-01-01
      • 1970-01-01
      • 2018-03-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多