通过分配大量内存来跟踪堆损坏
Track down heap corruption by allocating lots of memory?
在我的程序中,我遇到了以下错误:
free(): invalid size
Aborted (core dumped)
运行GDB时,我发现这发生在向量的析构函数中:
#0 0x00007ffff58e8c01 in free () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x0000555555dd44e2 in __gnu_cxx::new_allocator<int>::deallocate (this=0x7fffffff6bf0, __p=0x555557117810) at /usr/include/c++/7/ext/new_allocator.h:125
#2 0x0000555555dcfbd7 in std::allocator_traits<std::allocator<int> >::deallocate (__a=..., __p=0x555557117810, __n=1) at /usr/include/c++/7/bits/alloc_traits.h:462
#3 0x0000555555dc85e6 in std::_Vector_base<int, std::allocator<int> >::_M_deallocate (this=0x7fffffff6bf0, __p=0x555557117810, __n=1)
at /usr/include/c++/7/bits/stl_vector.h:180
#4 0x0000555555dc49e1 in std::_Vector_base<int, std::allocator<int> >::~_Vector_base (this=0x7fffffff6bf0, __in_chrg=<optimized out>)
at /usr/include/c++/7/bits/stl_vector.h:162
#5 0x0000555555dbc5c9 in std::vector<int, std::allocator<int> >::~vector (this=0x7fffffff6bf0, __in_chrg=<optimized out>) at /usr/include/c++/7/bits/stl_vector.h:435
#6 0x0000555556338081 in Gambit::Printers::HDF5Printer2::get_buffer_idcodes[abi:cxx11](std::vector<Gambit::Printers::HDF5MasterBuffer*, std::allocator<Gambit::Printers::HDF5MasterBuffer*> > const&) (this=0x555556fd8820, masterbuffers=...) at /home/farmer/repos/gambit/copy3/Printers/src/printers/hdf5printer_v2/hdf5printer_v2.cpp:2183
最后一行代码就是:
std::vector<int> alllens(myComm.Get_size());
首先,我不太明白为什么在这里调用析构函数,但假设它是向量动态构建的正常部分,那么我想这个错误一定是由于某种堆损坏造成的。
不过,我还不完全理解,是不是代码的其他部分以前非法访问了应该分配给这个向量的内存?
其次,我尝试过通过Intel Inspector运行它,我确实发现了一堆"无效内存访问"answers"未初始化内存访问"问题,但在我使用的库中,比如HDF5,它们看起来都像误报。
是否有一些代码内的方法可以缩小问题的确切来源?例如,由于它是由动态内存分配触发的,我可以在代码中越来越早地开始分配巨大的数组,以尝试在更接近崩溃源的地方触发崩溃吗?我试着四处寻找这样的东西是否有效或有用,但没有找到任何信息,所以也许这不是一个好主意?
因此,我通过一些MPI例程破坏了堆,即缓冲区长度等参数不正确。不幸的是,MPI库中发生了很多疯狂的事情,所以像Intel Inspector这样的内存分析器在查找它时没有那么有用。
然而,我了解了Address Sanitizer(https://en.wikipedia.org/wiki/AddressSanitizer)它与现代GNU编译器一起提供,结果证明它很棒!在我的CMake项目中根据它进行编译(来自https://gist.github.com/jlblancoc/44be9d4d466f0a973b1f3808a8e56782)
cmake .. -DCMAKE_CXX_FLAGS="-fsanitize=address -fsanitize=leak -g"
-DCMAKE_C_FLAGS="-fsanitize=address -fsanitize=leak -g"
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address -fsanitize=leak"
-DCMAKE_MODULE_LINKER_FLAGS="-fsanitize=address -fsanitize=leak"
使用运行
export ASAN_OPTIONS=fast_unwind_on_malloc=0
(不知道这是否真的必要(,当我的堆损坏发生时,收到了一个极好的回溯:
==12748==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000521340 at pc 0x7fda5011577a bp 0x7ffe231c55e0 sp 0x7ffe231c4d88
WRITE of size 32 at 0x602000521340 thread T0
#0 0x7fda50115779 (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x79779)
#1 0x7fda4fcd84e3 (/usr/lib/x86_64-linux-gnu/libmpich.so.0+0xf24e3)
#2 0x7fda4fc228d7 (/usr/lib/x86_64-linux-gnu/libmpich.so.0+0x3c8d7)
#3 0x7fda4fc23a26 (/usr/lib/x86_64-linux-gnu/libmpich.so.0+0x3da26)
#4 0x7fda4fc2316c (/usr/lib/x86_64-linux-gnu/libmpich.so.0+0x3d16c)
#5 0x7fda4fc2406c in PMPI_Gather (/usr/lib/x86_64-linux-gnu/libmpich.so.0+0x3e06c)
#6 0x55e0c18586b0 in void Gambit::GMPI::Comm::Gather<unsigned long>(std::vector<unsigned long, std::allocator<unsigned long> >&, std::vector<unsigned long, std::allocator<unsigned long> >&, int) /home/farmer/repos/gambit/copy3/Utils/include/gambit/Utils/mpiwrapper.hpp:450
...etc...
它直接指向我搞砸的MPI调用。太神了
但为了回答我的OP问题,我分配大量堆内存以触发更接近问题的崩溃的想法并没有真正奏效。不知道为什么。我想我只是不明白引擎盖下面发生了什么。事实上,我看到崩溃的地方是代码中MPI调用之前的,所以这很令人困惑。我猜编译器移动了一些东西?我确实关闭了优化,但我想二进制中的操作顺序仍然可能与我预期的不同?
- 为什么会发生堆损坏
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 平均图像时图像损坏
- 如何针对特定情况调试和修复此双自由内存损坏问题
- 光线跟踪器灯光反射错误
- 人脸跟踪arduino代码的优化
- 跟踪滚动条上的鼠标事件
- 为什么C中的通用链表中存储的数据已损坏
- gdb错误:Backtrace已停止:上一帧与此帧相同(堆栈已损坏?)
- 如何使用新运算符跟踪在循环中创建的 QLabel
- C++双重释放或损坏(out)
- 捕获标准输出以压缩并使用 CTRL-C 中断会给出损坏的 zip 文件
- 使用全局声明的向量时,C++双重释放错误/损坏
- C++:跟踪类对象
- 用于解析 win64 堆栈跟踪的命令行客户端(可以访问符号服务器)
- 跟踪日志中的T.11803()是什么意思?
- 变量周围的堆栈'...'已损坏
- 通过分配大量内存来跟踪堆损坏
- 跟踪内存损坏的特定调试技巧/工具
- "this"指针在堆栈跟踪中损坏