2015-11-11 11 views
11

プログラムで失敗したアサートをキャプチャしようとしています。私は、カスタム関数またはマクロではなく、assert()を直接呼び出すライブラリを使用しています。このライブラリ内には、現在いくつかの移植関連のバグをトレースしようとしています。関与するものすべてがg ++のデバッグシンボルでコンパイルされています。gdbで失敗したアサートを中断する適切な方法は何ですか?

私が見つけた最も良い解決策は、assert式の条件で、ファイルの行を破ることです。これは、失敗する前にアサートで停止することができますが、恐ろしい解決策です。おそらく失敗するアサーションごとに特別な設定が必要で、IDEからはうまく動作せず、一般的にはあまりにも多くの労力が必要です。

どのように私は上の任意のを破ることができるのassertの呼び出しの範囲内でコールスタックと変数の検査を可能にするような方法でGDB &のgccを使用してASSERT失敗?

解決策では、アサーションの失敗を破棄して実行を続けることができればさらに良いでしょう。

+0

Visual StudioのWindowsでは、破損は、失敗した 'assert'のデフォルト動作です。私は* nix世界ではそうではないことに驚いています - 失敗した 'assert'は通常そこで何をしますか? – Angew

+4

gdbでは、プログラムが実行される前に、関数abort()でブレークポイントを追加するために 'break abort'(または単に' b abort')を使うことができます。これは、アサーションが失敗したときにバックトレースを作ることを可能にします(あるときは 'abort()'を呼び出すと仮定します;代わりに 'exit()'を呼び出す実装もあります)。しかし、実行を継続することについてはわからない。 – notmyfriend

+2

通常これはassert()がabortを呼び出すときにデフォルトで動作し、abortはSIGABRTシグナルを発生させます。gdbはデフォルトでそのシグナルを破り、スタックを検査したり、スタックを上/下に移動したりすることができます。 assert()を含む関数に渡し、変数を検査します。 – nos

答えて

11

abort()にブレークポイントを設定するのが最善の答えです。

break abort gdbのCLIにあります。

+0

元のポスターと@notmyfriendはどちらも自分のコメントに回答を掲載しましたが、正式な回答を書いて、忘れてしまったときに何度かこのページに戻った後、すべてのコメントを読み直してそれは、私はそれを書いているだけだった! –

+2

これは天才です! – Antonio

3

ませbreakがちょうどプロンプト

abort()btを入力し、必要ありませんが、信号が発生することが原因となり、GDBはデフォルトですでに信号に分割します。

例えば:そして

#include <assert.h> 

void g(int i) { 
    assert(0); 
} 

void f(int i) { 
    g(i); 
} 

int main(void) { 
    f(1); 
} 

gcc -std=c99 -O0 -ggdb3 -o a a.c 
gdb -ex run ./a 

それからちょうど入力btシェル中:

既に関数値を示す
(gdb) bt 
#0 __GI_raise ([email protected]=6) at ../sysdeps/unix/sysv/linux/raise.c:58 
#1 0x00007ffff7a483ea in __GI_abort() at abort.c:89 
#2 0x00007ffff7a3ebb7 in __assert_fail_base (fmt=<optimized out>, [email protected]=0x555555554788 "0", [email protected]=0x555555554784 "a.c", [email protected]=4, 
    [email protected]=0x55555555478a <__PRETTY_FUNCTION__.1772> "g") at assert.c:92 
#3 0x00007ffff7a3ec62 in __GI___assert_fail (assertion=0x555555554788 "0", file=0x555555554784 "a.c", line=4, function=0x55555555478a <__PRETTY_FUNCTION__.1772> "g") 
    at assert.c:101 
#4 0x00005555555546ca in g (i=1) at a.c:4 
#5 0x00005555555546df in f (i=1) at a.c:8 
#6 0x00005555555546f0 in main() at a.c:12 

f (i=1))。

そして、あなたはまた、いつものように行うことができます:Ubuntuの16.10、GDB 7.11でテスト

(gdb) f 4 
#4 0x00005555555546ca in g (i=1) at a.c:4 
4   assert(0); 
(gdb) p i 
$1 = 1 

を。

0

上記の回答がうまくいかない場合は、__assert_fail機能を中断する可能性があります。

break __assert_fail 

名前はおそらく実装に依存しますが、プラットフォーム上でassertマクロの定義を見れば、簡単に見つかるはずです。これにより、SIGABRTの前に壊れることができます。

関連する問題