有些時候我們在一段 C/C++ 代碼的時候,由於對一個非法內存進行了操作,在程序運行的過程中,出現了“Segmentation fault (core dumped)”——段錯誤。
呵呵,這種問題我想很多人會經常遇到。遇到這種問題是非常無語的,只是提示了"段錯誤",接着什麼都沒有,如果我們一味的去看代碼找太疼苦了,因爲我們都相信自己寫的代碼沒問題,現實就是現實。接着,我們可能通過打印來定位到段錯誤的位置,這樣會有個問題,如果代碼量大,我們需要打印很多信息才能找到“段錯誤”的位置(這種辦法實在太笨了),而往往有些時候,“段錯誤”光靠打印不一定能找出來。接下來,給大家介紹通過gdb快速定位“段錯誤”的位置。
GDB是GNU開源組織發佈的一個強大的UNIX下的程序調試工具。或許,各位比較喜歡那種圖形界面方式的,像VC、BCB等IDE的調試,但如果你是在UNIX平臺下做軟件,你會發現GDB這個調試工具有比VC、BCB的圖形化調試器更強大的功能。所謂“寸有所長,尺有所短”就是這個道理。
首先,要確保安裝了gdb調試工具,在終端可通過“which gdb”查看:
編譯 C/C++ 代碼,加上 -g 參數,代表在可執行文件中加入標準調試信息。
接着,通過“./”運行可執行程序,如果出現“段錯誤”,正常情況下會在程序同級目錄下生成一個core文件(如RedHat),但是,有些環境卻不會生成core文件(如Ubuntu),core文件的生成跟你當前系統的環境設置有關係。當一個程序奔潰時,在進程當前工作目錄的core文件中複製了該進程的存儲圖像。core文件僅僅是一個內存映像(同時加上調試信息),主要用來調試的。
在 redhat 6(64位)環境下測試:
C++測試代碼如下:
#include <iostream>
using namespace std;
void test()
{
int *i = NULL;
*i = 250;
}
int main(int argc, char*argv[])
{
test();
return 0;
}
1)編譯(加上 -g )、執行程序,生產一個 core.* 文件:
2)啓動gdb,利用 core.* 文件快速定位“段錯誤”的位置。
#gdb -q 程序名 [corefile]。如本例中:gdb -q a.out core.6922,在gdb界面中輸入 where 查看“段錯誤”位置。
在ubuntu 14.04(64位)環境下測試:
C測試代碼如下:
#include <stdio.h>
#include <string.h>
void test()
{
char *p = NULL;
strcpy(p, "123");
}
int main(int argc, char*argv[])
{
printf("111111111111\n");
test();
printf("2222222222222\n");
return 0;
}
1)編譯(加上 -g )、執行程序,發現同級目錄並沒有生產 core 文件:
2)core文件的生成跟你當前系統的環境設置有關係,可以用下面的語句設置讓其生成 core 文件:ulimit -c unlimited。core 文件生成的位置一般於運行程序的路徑相同,在ubuntu下文件名一般爲core。
3)用gdb來調試core文件:gdb a.out core
4)在gdb字符界面中敲“where”查看更詳細信息。
GDB調試程序用法 http://www.linuxidc.com/Linux/2013-06/86044.htm
GDB+GDBserver無源碼調試Android 動態鏈接庫的技巧 http://www.linuxidc.com/Linux/2013-06/85936.htm
使用hello-gl2建立ndk-GDB環境(有源碼和無源碼調試環境) http://www.linuxidc.com/Linux/2013-06/85935.htm
在Ubuntu上用GDB調試printf源碼 http://www.linuxidc.com/Linux/2013-03/80346.htm
Linux下用GDB調試可加載模塊 http://www.linuxidc.com/Linux/2013-01/77969.htm
Ubuntu下使用GDB斷點Go程序 http://www.linuxidc.com/Linux/2012-06/62941.htm
使用GDB命令行調試器調試C/C++程序 http://www.linuxidc.com/Linux/2014-11/109845.htm