GDB 除錯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才有效。
簡單示例: