Comment détecter le point d’un débordement de stack

J’ai le problème suivant avec mon programme C: Quelque part un débordement de stack. Malgré la compilation sans optimisation et avec les symboles du débogueur, le programme se ferme avec cette sortie (à l’intérieur ou à l’extérieur de gdb sous Linux):

Programme terminé avec le signal SIGSEGV, erreur de segmentation. Le programme n’existe plus.

La seule façon dont je pouvais détecter que le débordement de la stack était en fait exécutait le programme via valgrind. Existe-t-il un moyen quelconque de forcer le système d’exploitation à enregistrer une trace de stack d’appels qui m’aiderait à localiser le problème?

Malheureusement, gdb ne me permet pas non plus de puiser facilement dans le programme.

Si vous autorisez le système à vider les fichiers core, vous pouvez les parsingr avec gdb:

$ ulimit -c unlimited # bash sentence to allow for infinite sized cores $ ./stack_overflow Segmentation fault (core dumped) $ gdb -c core stack_overflow gdb> bt #0 0x0000000000400570 in f () #1 0x0000000000400570 in f () #2 0x0000000000400570 in f () ... 

Quelques fois, j’ai vu un fichier de base mal généré qui contenait une trace de stack incorrecte, mais dans la plupart des cas, le bt générera une série d’appels récursifs à la même méthode.

Le fichier core peut avoir un nom différent pouvant inclure l’identifiant du processus, il dépend de la configuration par défaut du kernel dans votre système actuel, mais peut être contrôlé avec (exécuter en tant que root ou avec sudo):

 $ sysctl kernel.core_uses_pid=1 

Avec GCC, vous pouvez essayer ceci:

-fstack-protector
Emettez du code supplémentaire pour vérifier les dépassements de tampon, tels que les attaques par stack. Cela se fait en ajoutant une variable de garde aux fonctions contenant des objects vulnérables. Cela inclut les fonctions qui appellent alloca et les fonctions avec des tampons supérieurs à 8 octets. Les gardes sont initialisés lorsqu’une fonction est entrée puis vérifiée à la sortie de la fonction. Si un contrôle de sécurité échoue, un message d’erreur est imprimé et le programme se ferme.

-fstack-protector-all
Comme -fstack-protector sauf que toutes les fonctions sont protégées.

http://gcc.gnu.org/onlinedocs/gcc-4.3.3/gcc/Optimize-Options.html#Optimize-Options

Lorsqu’un programme meurt avec SIGSEGV, il vide normalement le kernel sous Unix. Pourriez-vous charger ce kernel dans le débogueur et vérifier l’état de la stack?