• 文章
  • 使用gdb除錯:查詢段錯誤
釋出
2012年8月15日 (最後更新:2012年8月15日)

使用gdb除錯:查詢段錯誤

評分:4.0/5 (267 票)
*****
要開始使用gdb,短小的示例是很好的。一旦你知道如何執行它(gdb 程式名),如何檢查和遍歷堆疊(bt, up, down),檢視你當前所在的程式碼(list),以及如何獲取變數的值(print),你就具備了處理最常見的崩潰(即段錯誤)的能力,並且你已經引導自己達到了可以自己學習更多東西的程度。

這是一個示例會話

1
2
3
4
5
6
7
8
9
10
11
12
#include<iostream>
using namespace std;

int main()
{

  int x = 7;
  int *p = 0;

  cout << "x = " << x;
  cout << "The pointer points to the value " << *p;
}


寫了一些程式碼,現在我將構建並執行它。我輸入的內容以粗體顯示,螢幕上的內容以斜體顯示。

j@j-desktop:~/badCode$ g++ 227.cpp
j@j-desktop:~/badCode$ ./a.out
段錯誤 (Segmentation fault)

糟糕,一個段錯誤。我將使用除錯符號重新構建它,然後在偵錯程式下執行它。

j@j-desktop:~/badCode$ g++ -g 227.cpp
j@j-desktop:~/badCode$ gdb ./a.out
GNU gdb (GDB) 7.1-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/j/badCode/a.out...done.
(gdb)
run
Starting program: /home/j/badCode/a.out

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400824 in main () at 227.cpp:13
13 cout << "指標指向的值是 " << *p;



思考:好吧,段錯誤發生在這行。我在這裡使用了一個指標 p。我最好檢查一下那個指標的值。

(gdb) print p
$1 = (int *) 0x0
思考:啊哈!指標的值為零 - 這是一個空指標。嘗試解引用它會導致段錯誤。讓我們看看附近的code。

(gdb) list
int x = 7;
int *p = 0;

cout << "x = " << x;
cout << "指標指向的值是 " << *p;
}




思考:啊,我從來沒有設定指標指向任何東西。這很容易修復。

(gdb) quit 除錯會話正在活動中。

次級程序 1 [程序 6779] 將被終止。

仍然退出? (y 或 n)


修復程式碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>

using namespace std;

int main()
{

  int x = 7;
  int *p = 0;
  p = &x;

  cout << "x = " << x;
  cout << "The pointer points to the value " << *p;
}


現在構建並執行
j@j-desktop:~/badCode$ g++ 227.cpp
j@j-desktop:~/badCode$ ./a.out
x = 7指標指向的值是 7

所以我們得到了它。我使用的命令是

gdb ./a.out - 啟動 gdb 並附加到我感興趣的程式。這不會啟動程式執行。
run - 啟動程式執行
print p - 顯示名為 p 的物件的值。
list - 顯示執行已暫停的行,以及周圍的程式碼行。
quit - 退出 gdb。

我建議你自己做類似的事情來練習一下。像這樣追蹤段錯誤非常容易。使用 gdb 僅需三十秒就可以確定確切的問題。我見過人們花費數小時試圖手動完成它,盯著程式碼,到處列印變數,僅僅因為他們不想進入偵錯程式。