web-dev-qa-db-fra.com

Quelle est la bonne façon de casser des assertions échouées dans gdb?

J'essaie de capturer des assertions échouées dans mon programme. J'utilise une bibliothèque qui appelle directement assert (), plutôt qu'une fonction ou une macro personnalisée. C'est dans cette bibliothèque que j'essaie actuellement de tracer plusieurs bogues liés au portage. Tout ce qui est impliqué a été compilé avec les symboles de débogage en g ++.

La meilleure solution que j'ai trouvée est de casser le fichier: ligne de l'assert, avec la condition de l'expression d'assert. Cela permet de s’arrêter sur l’affirmation avant qu’elle n’échoue, mais c’est une solution horrible. Cela nécessite une configuration spéciale pour chaque assertion qui risque d’échouer, ne fonctionnera pas dans mon IDE et demande beaucoup trop d’efforts en général.

Comment puis-je interrompre l'assertion any / en utilisant gdb & gcc de manière à permettre l'examen du stack et des variables entrant dans le champ de l'appel à l'assertion?

Ce serait encore mieux si la solution me permettait d'écarter l'échec de l'assert et de continuer à fonctionner.

17
user3995702

Définir un point d'arrêt sur abort() semble être la meilleure réponse.

break abort dans la CLI de gdb.

20
Peter M

Aucune break n'est requise sous Linux, il suffit de taper bt sur l'invite

abort() fait apparaître un signal sous Linux et GDB coupe déjà les signaux par défaut.

Par exemple.:

#include <assert.h>

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

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

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

Ensuite:

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

Ensuite, tapez simplement bt dans le shell:

(gdb) bt
#0  __GI_raise (sig=sig@entry=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>, assertion=assertion@entry=0x555555554788 "0", file=file@entry=0x555555554784 "a.c", line=line@entry=4, 
    function=function@entry=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

Ce qui montre déjà les valeurs de la fonction (f (i=1)).

Et vous pouvez aussi faire comme d'habitude:

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

Testé dans Ubuntu 16.10, gdb 7.11.

Si les réponses ci-dessus ne vous conviennent pas, essayez d’interrompre la fonction __assert_fail. 

break __assert_fail

Le nom dépend très probablement de la mise en œuvre, mais il est facile à trouver si vous regardez la définition de la macro assert sur votre plate-forme. Cela vous permettra de faire une pause avant SIGABRT.

1
Islam Boziev