2016-06-09 32 views
1

下面的程序不会触发断言失败:jemalloc未检测内存损坏

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触发中止失败?

+0

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

回答

0

这还不是很直接回答你的问题,但是...

未定义行为是不确定的。与释放的记忆一起玩进这个阵营。根据你的内存处理程序的实现,你可能会有一个“验证内存”类型的函数,它沿着你的空闲内存列表来查看是否存在某种类型的损坏,但即使这样也不会捕获所有内容特别是我自己熟悉jemalloc)。这可能是因为你的上面的代码碰到没有人关心的内存,所以不会被捕获。哎呀,你的std::cerr声明也在做未定义的行为,所以你甚至不能相信它的值(想想线程和操作系统抓取和改变内存等)

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

0

您期望jemalloc检测到一个写入释放的内存和一些释放内存的读取。

但jemalloc库不具备此功能。其调试模式仅检测导致内存损坏的一组有限的错误。例如双释放。

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

对于像jemalloc这样的库来检测对已释放内存的读/写操作,它必须将调试器样式的手表安装到每个释放区域中,这样会变得非常复杂并且会产生大量的运行时间开销 - 如果这样会扩大许多和大的分配,完全可以。

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

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