GDB 調試C++異常

http://www.cnblogs.com/zhenjing/archive/2011/06/01/gdb_fork.html

調試C++異常的兩種辦法:
1) 直接獲取異常的相關調用函數,在相應函數處設置斷點。
2) 利用gdb的catch throw/catch。(程序執行後,方有效)

如何獲取C++調用函數信息?
寫一個簡單C++程序,讓程序因異常而終止,bt查看調用棧,即可知道異常相關函數。

一個簡單程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <string>
// #include <exception>
#include <stdexcept>
 
void ter_handler(){
    printf("custom handler\n");
}
 
void test(){
    throw std::runtime_error("test function");
}
 
int main(int argc, char** argv)
{
    std::set_terminate(__gnu_cxx::__verbose_terminate_handler);
    // std::set_terminate(ter_handler);
 
    try{
    // throw 5;
    throw std::runtime_error("test error");
    }
    catch(...){
        printf("catch exception\n");
    }
 
    test();
    return 0;
}


g++ -o test exception.cc
gdb ./test
Program received signal SIGABRT, Aborted.
0x0000003cf592e2ed in raise () from /lib64/tls/libc.so.6
(gdb) bt
#0 0x0000003cf592e2ed in raise () from /lib64/tls/libc.so.6
#1 0x0000003cf592fa3e in abort () from /lib64/tls/libc.so.6
#2 0x0000003cf86b1138 in __gnu_cxx::__verbose_terminate_handler () from /usr/lib64/libstdc++.so.6
#3 0x0000003cf86af166 in __cxa_call_unexpected () from /usr/lib64/libstdc++.so.6
#4 0x0000003cf86af193 in std::terminate () from /usr/lib64/libstdc++.so.6
#5 0x0000003cf86af293 in __cxa_throw () from /usr/lib64/libstdc++.so.6
#6 0x0000000000400e9f in test ()
#7 0x0000000000400f9d in main ()

從上述調用棧,可以得知異常由__cxa_throw ()拋出,可在該函數處設置斷點,從而得知“異常出自哪裏”。

測試環境:
Linux bclnx64 2.6.9-34.ELsmp #1 SMP
GNU gdb Red Hat Linux (6.3.0.0-1.96rh)
Copyright 2004 Free Software Foundation, Inc.

上述給出的獲取異常調用函數信息的方法,應該和操作系統和調試器無關,其他平臺類似。

1) 直接獲取異常的相關調用函數,在相應函數處設置斷點。
利用前一步驟的信息,直接b __cxa_throw,即可設置有效斷點。

2) 利用gdb的catch throw/catch
該方法也很通用,但有一個需要注意的地方:在程序執行之前,catch throw/catch是無效的,需要在程序執行之後(先在main處設置斷點),使用catch throw纔有效。

簡單示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
nochen@bclnx64 ~/test$ gdb ./test
GNU gdb Red Hat Linux (6.3.0.0-1.96rh)
Copyright 2004 Free Software Foundation, Inc.
 
(gdb) b __cxa_throw
Function "__cxa_throw" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (__cxa_throw) pending.
(gdb) r
Starting program: /home/nochen/test/test
(no debugging symbols found)
Breakpoint 2 at 0x3cf86af230
Pending breakpoint "__cxa_throw" resolved
 
Breakpoint 2, 0x0000003cf86af230 in __cxa_throw () from /usr/lib64/libstdc++.so.6
(gdb) bt
#0  0x0000003cf86af230 in __cxa_throw () from /usr/lib64/libstdc++.so.6
#1  0x0000000000400f5b in main ()
(gdb) c
Continuing.
catch exception
 
Breakpoint 2, 0x0000003cf86af230 in __cxa_throw () from /usr/lib64/libstdc++.so.6
(gdb) bt
#0  0x0000003cf86af230 in __cxa_throw () from /usr/lib64/libstdc++.so.6
#1  0x0000000000400e9f in test ()
#2  0x0000000000400f9d in main ()
(gdb) c
Continuing.
terminate called after throwing an instance of 'std::runtime_error'
  what():  test function
 
Program received signal SIGABRT, Aborted.
0x0000003cf592e2ed in raise () from /lib64/tls/libc.so.6
(gdb) q
The program is running.  Exit anyway? (y or n) y
 
===================================
 
nochen@bclnx64 ~/test$ gdb ./test
(gdb) b main
Breakpoint 1 at 0x400ea4
(gdb) r
Starting program: /home/nochen/test/test
(no debugging symbols found)
 
Breakpoint 1, 0x0000000000400ea4 in main ()
(gdb) catch throw
Catchpoint 2 (throw)
(gdb) c
Continuing.
 
Catchpoint 2 (exception thrown)
0x0000003cf86af230 in __cxa_throw () from /usr/lib64/libstdc++.so.6
(gdb) bt
#0  0x0000003cf86af230 in __cxa_throw () from /usr/lib64/libstdc++.so.6
#1  0x0000000000400f5b in main ()
(gdb) c
Continuing.
catch exception
 
Catchpoint 2 (exception thrown)
0x0000003cf86af230 in __cxa_throw () from /usr/lib64/libstdc++.so.6
(gdb) bt
#0  0x0000003cf86af230 in __cxa_throw () from /usr/lib64/libstdc++.so.6
#1  0x0000000000400e9f in test ()
#2  0x0000000000400f9d in main ()
(gdb) c
Continuing.
terminate called after throwing an instance of 'std::runtime_error'
  what():  test function
 
Program received signal SIGABRT, Aborted.
0x0000003cf592e2ed in raise () from /lib64/tls/libc.so.6
(gdb)


發佈了81 篇原創文章 · 獲贊 7 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章