例如,下面的代碼導致 munmap_chunk(): invalid pointer
#include <vector>
int main(int argc, char* argv[]) {
std::vector<int> foo(10, 0);
std::vector<int> bar(10, 1);
for(int i = 0; i < 20; i ) {
foo[i] = 42;
}
bar.clear(); // causes munmap_chunk(): invalid pointer
}
在這個簡單的例子中,我可以很容易地猜到它bar是foo在堆記憶體中分配的,所以可以猜到一些foo對bar. 所以修復這個錯誤相當容易。
然而在實際應用中,情況可能要復雜得多,我們無法輕易猜測堆記憶體分配。
所以我的問題是:
- 有沒有辦法顯示如何在堆中分配變數?
- 是否可以監控哪個函式意外破壞了某些記憶體?
uj5u.com熱心網友回復:
有沒有辦法顯示如何在堆中分配變數?
是:您可以檢查vector將在除錯器中使用的位置。例如(使用您的程式)和 GDB:
(gdb) start
Temporary breakpoint 1 at 0x1185: file t.cc, line 3.
Starting program: /tmp/a.out
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdbb8) at t.cc:3
3 std::vector<int> foo(10, 0);
(gdb) n
4 std::vector<int> bar(10, 1);
(gdb) p/r foo
$1 = {<std::_Vector_base<int, std::allocator<int> >> = {_M_impl = {<std::allocator<int>> = {<__gnu_cxx::new_allocator<int>> = {<No data fields>}, <No data fields>}, <std::_Vector_base<int, std::allocator<int> >::_Vector_impl_data> = {_M_start = 0x55555556aeb0, _M_finish = 0x55555556aed8, _M_end_of_storage = 0x55555556aed8}, <No data fields>}}, <No data fields>}
(gdb) n
5 for(int i = 0; i < 20; i ) {
(gdb) p/r bar
$2 = {<std::_Vector_base<int, std::allocator<int> >> = {_M_impl = {<std::allocator<int>> = {<__gnu_cxx::new_allocator<int>> = {<No data fields>}, <No data fields>}, <std::_Vector_base<int, std::allocator<int> >::_Vector_impl_data> = {_M_start = 0x55555556aee0, _M_finish = 0x55555556af08, _M_end_of_storage = 0x55555556af08}, <No data fields>}}, <No data fields>}
在這里您可以看到foo將使用位置0x55555556aeb0through0x55555556aed8和bar將使用0x55555556aee0through 0x55555556af08。
不過請注意,這些位置可能從運行改變運行,特別是在多執行緒程式,使得該技術非常難以使用。
如果 Address Sanitizer 可以發現您的問題,那將是更快、更可靠的方法。
是否可以監控哪個函式意外破壞了某些記憶體?
是的:這就是觀察點的用途。例如,我們不希望 指向的位置foo._M_impl._M_end_of_storage發生變化,因此我們可以在其上設定一個觀察點:
(gdb) start
Temporary breakpoint 1 at 0x1185: file t.cc, line 3.
Starting program: /tmp/a.out
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdbb8) at t.cc:3
3 std::vector<int> foo(10, 0);
(gdb) n
4 std::vector<int> bar(10, 1);
(gdb) n
5 for(int i = 0; i < 20; i ) {
(gdb) watch *(int*)0x55555556aed8
Hardware watchpoint 2: *(int*)0x55555556aed8
(gdb) c
Continuing.
Hardware watchpoint 2: *(int*)0x55555556aed8
Old value = 49
New value = 42
main (argc=1, argv=0x7fffffffdbb8) at t.cc:5
5 for(int i = 0; i < 20; i ) {
(gdb) p i
$1 = 10 <-- voila, found the place where overflow happened.
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/322006.html
