2015-11-11 6 views
11

Ich versuche fehlgeschlagene Behauptungen in meinem Programm zu erfassen. Ich verwende eine Bibliothek, die direkte Aufrufe von assert() statt einer benutzerdefinierten Funktion oder eines Makros ausführt. In dieser Bibliothek versuche ich derzeit, mehrere Probleme im Zusammenhang mit der Portierung zu finden. Alles was dazugehört wurde mit Debug-Symbolen in g ++ kompiliert.Was ist der richtige Weg, um fehlgeschlagene Behauptungen in gdb zu brechen?

Die beste Lösung, die ich gefunden habe, bricht an der Datei: Zeile der Assert, mit der Bedingung der Assert-Ausdruck. Dies ermöglicht das Anhalten der Assert, bevor es fehlschlägt, ist aber eine schreckliche Lösung. Es erfordert ein spezielles Setup für jede möglicherweise fehlgeschlagene Assertion, funktioniert nicht von meiner IDE und ist im Allgemeinen viel zu viel Aufwand.

Wie kann ich auf brechen jede Assertion fehlgeschlagen so gdb & gcc verwenden, die Prüfung der Aufrufliste und Variablen im Rahmen des assert Anruf erlaubt?

Es wäre noch besser, wenn die Lösung mir erlauben würde, den Fehler der Assert zu verwerfen und weiter zu laufen.

+0

In Windows in Visual Studio ist das Brechen das Standardverhalten eines fehlgeschlagenen 'assert'. Ich bin überrascht, dass das in der * nix-Welt nicht der Fall ist - was macht ein gescheitertes 'assert' dort normalerweise? – Angew

+4

In gdb können Sie vor dem Ausführen des Programms 'break abort' (oder nur' b abort') verwenden, um einen Breakpoint bei der Funktion abort() einzufügen. Dadurch können Sie zumindest eine Rückverfolgung durchführen, wenn eine Assertion fehlschlägt (vorausgesetzt, sie ruft 'abort()' auf, wenn dies der Fall ist; einige Implementierungen können stattdessen 'exit()' aufrufen. Nicht sicher über die weitere Ausführung. – notmyfriend

+2

Normalerweise funktioniert dies standardmäßig, da assert() Aufrufe abbricht, und abort das Signal SIGABRT auslöst, und gdb bricht dieses Signal standardmäßig ab und erlaubt Ihnen, den Stapel zu prüfen, den Stapel nach oben/unten zu bewegen, z. zu Ihrer Funktion, die die assert() - und inspect-Variablen usw. enthält. – nos

Antwort

11

Das Setzen eines Haltepunktes auf abort() scheint die beste Antwort zu sein.

break abort in gdb CLI.

+0

Das ursprüngliche Poster und @notmyfriend haben beide Antworten in ihren Kommentaren gepostet, aber nachdem jemand vorgeschlagen hat, eine offizielle Antwort zu schreiben und einige Male wieder auf diese Seite zu gehen, wenn ich es vergessen habe und dann alle Kommentare erneut lesen muss es war, ich schreibe es gerade auf! –

+2

Das ist Genie! – Antonio

3

Kein break benötigt wird, geben Sie einfach bt an der Eingabeaufforderung

abort() bewirkt, dass ein Signal angehoben werden, und gdb bricht bereits auf Signale standardmäßig.

Z. B .:

#include <assert.h> 

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

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

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

Dann:

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

Dann geben Sie einfach bt in der Schale:

(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 

, die bereits die Funktionswerte zeigt (f (i=1)).

Und Sie können auch wie gewohnt tun:

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

Getestet in Ubuntu 16.10, gdb 7.11.

0

Wenn die oben genannten Antworten für Sie nicht funktionieren, können Sie versuchen, die Funktion __assert_fail zu unterbrechen.

break __assert_fail 

-Name ist höchstwahrscheinliche Umsetzung - abhängig, aber es ist leicht zu finden, wenn Sie bei der Bestimmung des assert-Makro auf Ihrer Plattform suchen. Dadurch können Sie vor SIGABRT brechen.