http://www.cnblogs.com/zhenjing/archive/2011/06/01/gdb_fork.html
调试C++异常的两种办法:
1) 直接获取异常的相关调用函数,在相应函数处设置断点。
2) 利用gdb的catch throw/catch。(程序执行后,方有效)
如何获取C++调用函数信息?
写一个简单C++程序,让程序因异常而终止,bt查看调用栈,即可知道异常相关函数。
一个简单程序:
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) 利用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)
|