2015-11-11 9 views
11

Sto tentando di catturare affermazioni fallite nel mio programma. Sto usando una libreria che effettua chiamate dirette ad assert(), piuttosto che una funzione o una macro personalizzata, ed è all'interno di questa libreria che sto attualmente cercando di rintracciare diversi bug relativi al porting. Tutto ciò che è coinvolto è stato compilato con i simboli di debug in g ++.Qual è il modo corretto per interrompere affermazioni non riuscite in gdb?

La soluzione migliore che ho trovato è quella di infrangere il file: linea dell'asserzione, con la condizione dell'espressione assert. Questo permette di fermarsi prima che fallisca, ma è una soluzione orribile. Richiede una configurazione speciale per ogni affermazione che potrebbe non riuscire, non funzionerà dal mio IDE, ed è di gran lunga troppo impegnativo in generale.

Come posso rompere il qualsiasi fallito assert usando gdb & gcc in modo tale che consente l'esame della stack e le variabili nell'ambito di applicazione della chiamata assert?

Sarebbe ancora meglio se la soluzione mi permettesse di scartare il fallimento dell'assert e continuare a correre.

+0

Su Windows in Visual Studio, interrompere è il comportamento predefinito di un 'assert' non riuscito. Sono sorpreso che non sia il caso del mondo * nix - cosa fa normalmente un "assert" fallito? – Angew

+4

In gdb, prima dell'esecuzione del programma, è possibile usare 'break abort' (o semplicemente' b abort') per aggiungere un breakpoint alla funzione abort(). Ciò consentirà almeno di fare un backtrace quando un'asserzione fallisce (assumendo che richiami 'abort()' quando lo fa, alcune implementazioni possono chiamare 'exit()' invece). Non sono sicuro di continuare l'esecuzione però. – notmyfriend

+2

Normalmente questo funziona di default, come le chiamate assert() abort, e abort alza il segnale SIGABRT, e gdb per default interruzioni su quel segnale, consentendo di ispezionare lo stack, spostare su/giù la pila, ad es. alla tua funzione contenente l'assert() e controlla le variabili e così via. – nos

risposta

11

L'impostazione di un punto di interruzione su abort() sembra essere la risposta migliore.

break abort nella CLI di gdb.

+0

Il poster originale e @notmyfriend hanno postato entrambe le risposte nei loro commenti, ma dopo aver suggerito a qualcuno di scrivere una risposta ufficiale, e di essere tornati su questa pagina alcune volte ogni volta che ho dimenticato, e quindi dover rileggere tutti i commenti per capire cosa era, sto solo scrivendo! –

+2

Questo è genio! – Antonio

3

No break è necessario, basta digitare bt sul prompt

abort() provoca un segnale di essere sollevato, e gdb rompe già segnali di default.

Es .:

#include <assert.h> 

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

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

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

Poi:

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

Poi digitate bt nel guscio:

(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 

Che mostra già i valori della funzione (f (i=1)).

E si può anche fare come al solito:

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

testato in Ubuntu 16.10, gdb 7.11.

0

Se le risposte sopra suggerite non funzionano per te, puoi provare a interrompere la funzione __assert_fail.

break __assert_fail 

nome è probabilmente implementazione - dipendente, ma è facile da trovare se si guarda alla definizione di macro assert sulla tua piattaforma. Questo ti permetterà di rompere prima di SIGABRT.

Problemi correlati