2016-12-13 64 views
0

我有一個核心gdb會話,它表明在讀取其中一個成員時,在指針的解引用中存在段錯誤。該指針的值非空。我認爲這意味着該進程無法訪問內存地址。如何從核心的postmortem gdb會話中獲取此信息?我該如何讓gdb告訴我一個給定地址的內存特徵

例如,假設下面的程序:

#include <iostream> 

using namespace std; 

int 
main(int argc, char* argv[]) 
{ 
    int *ptr = new int(5); 
    cout << "I can access it here: " << *ptr << endl; 

    delete ptr; 

    cout << "But I shouldn't do so here: " << *ptr << endl; 
    return 0; 
} 

如果我調試這個程序用gdb:

$ g++ -g -Wall test.cc -o test 
$ gdb ./test 
(gdb) b 13 
... 
Breakpoint 1 at 0x400943: file test.cc, line 13. 
(gdb) run 
Starting program: /usr/home/nfs/bneradt/test/test 
I can access it here: 5 

Breakpoint 1, main (argc=1, argv=0x7fffffffe348) at test.cc:13 
13   cout << "But I shouldn't do so here: " << *ptr << endl; 
(gdb) 

我可以從PTR得到什麼樣的內存信息?我可以確定ptr指向釋放內存嗎?由於在我正在調試的核心(不在上面的玩具測試二進制文件中),我得到了一個段錯誤解引用 - 即從一個指針讀取,而不是寫入一個指針,我想原始內存位置被分頁出去,因此不是過程可訪問的內存?我可以從gdb會話中確定嗎?

+0

可能重複的[C + +刪除 - 它刪除我的對象,但我仍然可以訪問數據?](http://stackoverflow.com/questions/1930459/c-delete-it-deletes-my-objects-but-我仍然可以訪問數據) – user4581301

+0

C++遵循一種只爲你所需要的付款的理念,所以它不會浪費時間來測試和阻止公然錯誤的。 – user4581301

+0

該帖子沒有回答我的問題。我並沒有問是否讀取釋放的內存地址會崩潰 - 在很多情況下顯然不會。我甚至在我的帖子中承認。我問的是gdb可以告訴我關於postmortem核心內存地址的內容。 – firebush

回答

2

gdb沒有動態分配的概念,也沒有關於釋放內存的想法。它可以告訴的地址是否被映射到進程的地址空間或不:

gdb> info files 
gdb> maintenance info sections 

但因爲你的程序有SIGSEGV崩潰,你已經知道它曾試圖訪問映射的地址。

其他工具可以檢測對已釋放內存的訪問。 valgrind通常是你的朋友,但不適用於驗屍調試。您需要運行valgrind下的程序以瞭解其行爲。

段引用很少意味着指針指向已釋放的內存。通常情況下,指針本身駐留在被釋放的內存中,並被重用和覆蓋。因此,

int** ptrarr = new int*[5]; 
ptrarr[3] = new int(5); 
// later 
delete [] ptrarr; 
// later still after many memory allocations 
int* ptr = ptrarr[3]; // ptrarr points to freed memory; UB but no segfault 
         // ptr contains a seemingly random value 
int num = *ptr;  // possible segfault 

從非檢測可執行文件的事後轉儲中提取這類信息非常困難。您需要熟悉mallocnew的內部工作,能夠追蹤其內部數據結構,並手動繪製出他們的競技場。這不是一項簡單的任務。使用具有保存調試符號的標準庫版本將有所幫助。如果做不到這一點,你可以嘗試並映射出你程序的內存,包括靜態/全局變量,堆棧變量,上面指向的所有分配的數據結構,以及其他分配的數據結構中指針指向的所有分配的數據結構。我知道沒有哪種工具能夠從驗屍轉儲中自動執行此操作,但理論上這些工具是可能的。

映射完程序存儲器或映射了程序存儲器的某些部分後,可以試着找出不同類型的不相關對象是否位於無效指針所在的地址。如果是這樣,你可能會得出這樣的結論:兩個對象中的一個可能被釋放,釋放後非法訪問的內存。

+0

'info proc'僅適用於實時調試,不適用於驗後('core')。 –

+0

@EmployedRussian Oops你是對的,編輯。 –

+0

謝謝,這非常有幫助。 – firebush

相關問題