以下程序不会触发断言失败:
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触发中止失败?
发布于 2016-06-10 01:26:24
这不是对你问题的直接回答,但是...
未定义的行为未定义。使用已释放的内存就属于这一阵营。根据您的内存处理程序的实现,您可能会有一个“验证内存”类型的函数,它会遍历您的空闲内存列表,以查看是否存在某种类型的损坏,但即使这样也不能捕获所有内容(特别是我自己并不熟悉jemalloc )。上面的代码可能会碰到没有人关心的内存,因此不会被捕获。见鬼,您的std::cerr语句也在执行未定义的行为,因此您甚至不能信任它的值(想想线程和OS抓取和更改内存等)。
这就是尽可能不在C++中直接使用指针的原因之一。管理生命周期的智能指针和容器可以自动防止几乎所有这些类型的错误。
发布于 2017-09-17 04:50:09
您期望jemalloc检测到对已释放内存的一次写入和对已释放内存的一些读取。
但是jemalloc库没有这个功能。它的调试模式只能检测导致内存损坏的一组有限的错误。例如,双释放。
这不是任意的限制,因为像jemalloc这样的库不能检测到任何类型的内存访问错误。这意味着作为一个库,它可以很容易地重载malloc()、/free()等并安装一个退出处理程序。因此,调试模式实现可以有效地实现有限的一组检查。当然,每个调试模式实现都会选择自己的折衷方案。例如,jemalloc在空闲时也不会检测到简单的缓冲区溢出,尽管其他具有调试功能的库(例如Solaris的libumem)实现了一种轻量级机制,其中会检查一些特殊尾部字节的完整性。
对于像jemalloc这样的库,为了检测对释放内存的读/写,它必须在每个释放的区域中安装调试器风格的监视器,这将非常复杂,并产生显着的运行时开销-如果这将扩展到许多和大量的分配。
关键是: jemalloc是一个错误的工具,用来检测对释放内存的写入(A)和读取(B)。
例如,随GCC和克隆一起提供的Address Sanitizer (-fsanitize=address)能够检测(A),但不能检测(B)。Valgrind (valgrind --tool=memcheck)能够同时检测(A)和(B),并将这些问题报告为对已释放块的无效读/写。与简单的分配器库调试模式相比,这两种工具的运行时开销肯定更高。由于valgrind的方法是模拟CPU,因此它的开销比Address Sanitizer高得多。
https://stackoverflow.com/questions/37732361
复制相似问题