Forum Programmation.c comment trouver l'origine d'un segmentation fault ?

Posté par  .
Étiquettes : aucune
0
13
mar.
2005
Bonjour,

Je suis en train de reprendre un vieux projet de jeu en C (conçu sous Dos avec gcc/allegro). Tout se passe à peu près bien, sauf que j'arrive à un moment à un "segmentation fault" dont je ne parviens pas à retrouver l'origine (même en plaçant des points d'arrêt sous kdevelop).

Il existe un moyen de savoir exactement quelle ligne des sources provoque le plantage ? Un "coredump" n'est-il pas sensé être créé à ce moment ? J'ai cherché un fichier ressemblant à "core" mais sans succès.

Merci
  • # générer le core dump

    Posté par  . Évalué à 1.

    Bon, j'ai réussi à progresser un (tout) petit peu :-) Pour le coredump; il semble que certaines distributions désactive la génération de ce fichier.

    On peut vérifier que le coredump sera bien généré avec la commande
    $ ulimit -c
    Si le nombre donné vaut 0, aucun coredump ne sera généré. D'après ce que j'ai trouvé, une taille de 1000 devrait suffire :
    $ ulimit -c 1000

    Maintenant, je lance mon programme et l'exécute jusqu'à atteindre le plantage, et j'ouvre le coredump avec gdb :

    % gdb ./testwin core.wxyz
    GNU gdb 6.3-debian
    [...]
    Failed to read a valid object file image from memory.
    Core was generated by `./testwin'.
    Program terminated with signal 6, Aborted.
    Cannot access memory at address 0x40016e28
    #0 0x402567ab in ?? ()
    (gdb) quit

    Bon ben je ne suis pas tellement plus avancé :-) D'après la doc que j'ai trouvé, j'aurais du avoir la liste d'appel des fonctions juste avant le plantage.

    Y a-t-il quelque chose (d'évident sûrement) que j'ai raté ?

    Merci
    • [^] # Re: générer le core dump

      Posté par  . Évalué à 3.

      Ben je crois qu'il faudrait augmenter la taille autorisee pour le coredump :
      ulimit -c unlimited

      (ma vie: l'appli sur laquelle je travaille peut me pondre des fois des cores de 50Mo voire plus, donc bon... Ton ulimit me semble un peu limite ;)
      • [^] # Re: générer le core dump

        Posté par  . Évalué à 1.

        En effet, c'est une bonne idée, merci ! En n'oubliant pas de nettoyer les core générés de temps en temps, sinon je vais tomber à court d'espace disque :-)

        Dans mon cas, j'ai vu qu'il existait un "liballegro4.1-dbg" (compilés avec les symboles de débuggage). Après l'avoir installé et compilé mon programme avec, gbd me sort enfin une liste conséquente d'appels. Bon, il ne remonte toujours pas jusqu'à mon programme, la dernière ligne faisant référence à libc6 ..

        Finalement, j'ai découvert un des trucs qui n'allait pas. Suite à un changement de taille d'une des images du jeu (je ne peux pas trop expliquer le détail ici), je provoquais un dépassement de tableau. Rien à voir avec allegro donc.

        Ce n'est pas typiquement le genre de trucs qu'on devrait pouvoir retrouver avec gdb ?
        • [^] # Re: générer le core dump

          Posté par  . Évalué à 1.

          Ce n'est pas typiquement le genre de trucs qu'on devrait pouvoir retrouver avec gdb ?

          Avec gdb je ne sais pas, mais avec valgrind, oui :)
    • [^] # Re: générer le core dump

      Posté par  (site web personnel) . Évalué à 4.

      1.Il faut aussi compiler le programme, avec l'option -g de gcc pour obtenir l'emplacement exacte de l'erreur
      2.Tu peux faire directement gdb ./testwin, la tu lance run et t'attend le segfault
      3.C'est pas un segmentation fault, mais un abort, donc volontaire par le programme.
      Un grep "abort()" -r lesources pourait aider
      4.Dans gdb tu peux faire bt pour voir quelles fonctions ont appellé la fonction planteuses
      • [^] # Re: générer le core dump

        Posté par  . Évalué à 1.

        1. Le makefile est généré par kdevelop. Le projet est réglé sur "full debug", donc c'est bon.

        2. Voilà un bon truc, merci :-) Il faut vraiment que je me penche sur la doc des outils comme gdb. C'est le genre de truc que j'aurais aimé apprendre à l'école :-)

        3. Ben en fait, il me sortais "abort" si je lançais le programme directement et "segmentation fault" à travers kdevelop. Comme c'est mon propre projet que je reprends, je sais qu'il n'y a aucun abort dans mon code, j'ignorais cet appel jusqu'à maintenant :-) Quoique cet appel se trouve peut-être dans une des fonctions d'allegro, bonne idée à creuser, merci -:)

        4. C'est la seule commande que je connaissais déjà dans gdb, avec quit :-)

        Merci pour ces pistes.
        • [^] # Et la pile ?

          Posté par  . Évalué à 2.

          Eh les gars, je n'ai vu encore personne faire état de la pile !

          Comme dit plus haut, on inclue les symboles de debuggage en compilant avec "-g", on lance gdb ./testwin, on fait run et on attend le segfault.

          crashme.c

          int main (void)
          {
          char * ptr =0;
          * ptr = '-';

          return 0;
          }

          $ gcc -g crashme.c -o crashme
          $ gdb crashme
          (gdb) run
          Program received signal SIGSEGV, Segmentation fault.
          0x08048346 in main () at crashme.c:5
          5 * ptr = '-';


          Et quand on veut savoir d'où on vient, on explore la pile avec un backtrace :
          (gdb) bt
          #0 0x08048346 in main () at crashme.c:5
          #1 0x40043c57 in __libc_start_main () from /lib/i686/libc.so.6


          Après il existe "b" pour placer un breakpoint, "s" (step) pour avancer d'une instruction, "n" (next) pour sortir de la fonction en cours, etc. et surtout "help".


          Enfin un conseil : Lâche KDevelop un moment ou l'on va croire que tu es perdu sans Visual Studios. Habitues-toi un moment à la ligne de commande, et reviens-y - si tu y tiens encore - quand tu seras devenu un guru ! :-)
          • [^] # Re: Et la pile ?

            Posté par  . Évalué à 2.

            Merci pour tes conseils. Je travaille justement sur la doc de gdb pour bien comprendre comment il fonctionne. Vu que les outils graphiques s'appuient simplement dessus, ca ne sera pas inutile :-)

            Sinon, je ne suis pas un fana de kdevelop à la base. J'ai passé le projet sous cet IDE il y a peu pour une histoire de confort, mais je reprends le C (et ce projet) après l'avoir lâché pour d'autres langages pendant longtemps, et je n'avais jamais eu l'occasion d'aborder ces programmes (gdb, valgrind...) voilà tout :-) Je manque cruellement de connaissances pour ce genre de choses qui sortent du langage et l'algorithmie, mais je sais encore écrire un makefile (je vérifie .. oui ! ouf !). Je dois être récupérable :-)

            Au boulot, je travaille sous 4D 6 et je peux te dire que je regrette l'absence d'outils en ligne de commande. On ne peut rien scripter, les sources sont enfermés dans un format binaire qui empêche tout accès par des outils extérieurs (impossible de faire un simple rechercher/remplacer global !). Pas moyen non plus d'automatiser des trucs (stats, compilation, maintenance de la base ..) un cauchemard, mais je m'égare.
  • # Gdb et printf ...

    Posté par  . Évalué à 3.

    Avec gdb, tu lances ton programme, il fait son segfault, et tu tapes 'bt' ... Tu auras toutes les infos nécessaires ...

    Il y a aussi la solution de poser des printf de partout dans ton code pour "tracer" le déroulement de ton code, et quand ça s'arrête, tu sais où ...

    Voilà, c'est le système D ...

    Sinon pense à utiliser un outil du genre de Valgrind pour débusquer tous tes problèmes d'allocation/déallocation/écriture/lecture en mémoire, car les segfault sont souvent dûs à des défauts de programmation à ces niveaux-là ...
    • [^] # Re: Gdb et printf ...

      Posté par  . Évalué à 2.

      En effet, printf permt déjà de réaliser un débugging de base (je l'utilise déjà pour tracer l'initialisation du jeu jusqu'à ce qu'il passe en mode graphique), mais le pas à pas ne me pose pas de problème en soi car ça fonctionne bien avec kdevelop :-)

      Le problème ici était que je ne voyais absolument pas d'où pouvait venir le plantage et ne savais où poser les points d'arrêts (ou les printf).

      Sinon, merci pour valgrind, je vais regarder de ce côté et voir comment il fonctionne.
  • # Efence

    Posté par  . Évalué à 4.

    Tu peux utiliser ElectricFence : http://perens.com/FreeSoftware/ElectricFence/(...)
    Grossièrement : quand tu l'actives, sa librairie "remplace" les malloc et realloc standards : ils allouent de la mémoire à la fin des blocs mémoire. Comme ça, quand t'as une erreur d'écriture dans un endroit non autorisé, le segfault est déclenché tout de suite, et donc tu seras bien plus proche du malloc que sans ElectricFence, où le segfault peut avoir lieu 15 minutes après le malloc "défectueux"...
  • # DDD

    Posté par  (site web personnel) . Évalué à 2.

    Si tu es alergique à gdb tu peux utiliser dd, un petit frontend pratique
    http://www.gnu.org/software/ddd/(...)

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.