IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Segmentation Fault incomprehensible


Sujet :

C++

  1. #1
    Membre averti
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Avril 2014
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2014
    Messages : 35
    Par défaut Segmentation Fault incomprehensible
    Bonjour,

    Mon code plante a l'execution avec le message d'erreur "segmentation fault" et, apres plusieurs heures d'arrachage de cheveux je n'arrive pas a resoudre le probleme.

    Pour expliquer mon probleme :
    - le programme lance une boucle de 150000 itérations ac les memes actions a chaque fois et plante au bout d'environ 110000 itérations
    - biarre : le programme ne plante jamais lors de la meme itération, un cous de sera 109987, l'autre coups ce sera 109567 (toujours assez proche de 109/110k mais jamais au meme endroit)... Je ne pas comment c'est ossible car il n'y a rien d'aléatoire dans mon programme donc je m'attendrai a ce que ca plante toujours au meme moment ou que ca plante pas du tout.
    - le code plante a l'appel d'une function virtuelle par une sous classe, Cette function est appele a chaque iteration sans probleme mais plante alors que ce sont exactement les memes éléments....

    Voila, si vous avez une quelconque idée du type d'erreur qui pourrait expliquer mon probleme, en particulier les cas ou on peut avoir un programme qui plante de maniere "aléatoire" sans raison particulière.

    Y a t-il moyen lorsqu'on l'on a ce type d'erreur d'avoir une explication plus approfondie (que simplement "Segmentation Fault") de ce qui a cause l'erreur ? En utilisant les debuggueur des IDE genre QT Creator ca peut m'aider peut-être ? Pour debugguer un programme quels sont les methodes efficaces / conseillés ? Car je suis débutant et ce que je fais est assez manuel en général : je mets des std::cout un peu partout dans le programme puis je le lance pour voir ou ca plante et je me demandais si il y avait plus simple et efficace....

    Merci pour votre aide !

  2. #2
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Par défaut
    Si le programme plante toujours entre la 109k et la 110k itération, on ne peut plus vraiment parler de plantage aléatoire, juste une petite incertitude sur l'itération précise.

    Quant à l'origine du problème, ce n'est souvent pas à la ligne où se produit la "segmentation fault" que se trouve le bug. Il s'agit d'une tentative d'accès en dehors des zones allouées.
    Les causes fréquentes sont les déréférencement de pointeur nul, non initialisé, libéré, hors scope, l'écriture au delà de la fin d'un tableau, des excès de récursivité, des accès simultanés par plusieurs threads, etc.

    Il existe pas mal d'outils permettant de surveiller et déboguer les accès mémoire, l'un des plus connus étant valgrind.

  3. #3
    Invité
    Invité(e)
    Par défaut
    salut,

    lorsque tu seg, tu peux générer un core (voir ulimit), puis utiliser gdb sur ton core pour avoir les dernières instructions avant le crash. Après comme pour toi c'est aléatoire je suis pas sûr que ca t'aide beaucoup.

    Comme ca arrive aux alentours des 100k, je verrais bien une fuite mémoire et une alloc refusée à partir d'une certaine itération..
    du coup (c'est jamais perdu) installes également valgrind (memcheck) et lance valgrind dessus pour voir si tu fuites pas.

  4. #4
    Membre averti
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Avril 2014
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2014
    Messages : 35
    Par défaut
    Merci pour vos reponses !

    Bon j'ai lance le memcheck de valgrind (sous Qt Creator Analyse--> Valgrind memory check) et la..... le code tourne parfaitement jusque la fin, je comprends pas du tout.

    Lorsque je le lance en ligne de commande dans la console sous linux ca plante mais pas lancer en "memory check".

  5. #5
    Membre chevronné
    Profil pro
    Consultant en technologies
    Inscrit en
    Octobre 2013
    Messages
    158
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Consultant en technologies

    Informations forums :
    Inscription : Octobre 2013
    Messages : 158
    Par défaut
    Ca s'appelle un Heisenbug

    * Est-ce que ton code est multithread ? Une data-race peut produire ce genre de bug (tu veux lire une variable initialisé par un autre thread, sauf qu'un jour le thread a pas eu le temps de finir...) puis lorsque tu instrumente le code tout à coup le thread a tout le temps le temps de finir. À nouveau Valgrind peut t'aider http://valgrind.org/docs/manual/hg-manual.html (Si ton projet est petit un papier et un crayon aussi)

    * Est-ce que ton code utilise des pointeurs (nus) ? Un pointeur effacé sous certaines conditions alors que tu dois encore y avoir accès peut provoquer ce genre de problème.

    Je dirais donc Valgrind (ou équivalent), remplacement/habillage des pointeurs. c'est quelques jours de boulots pas marrant, mais si ca résoud pas ton bug ca en résoudra d'autres que t'as pas encore vu.

  6. #6
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Comme les autres te l'ont déjà indiqué, une erreur de segmentation n'est que le symptôme du fait que tu es aller charcuter la mémoire de ton application. C'est le symptôme, pas la cause qui, elle, peut avoir énormément d'origines (la plupart ont d'ailleurs déjà été citées au moins une fois).

    Si ton programme fonctionne correctement en mode débug alors qu'il plante lamentablement en mode release, tu ne dois y voir qu'une chose : la confirmation du symptôme représenté par l'erreur de segmentation : tu vas bel et bien, à un moment donné, charcuter la mémoire et y foutre le bordel.

    Il faut en effet avoir conscience de deux choses :
    • le mode débug contient énormément d'informations supplémentaires par rapport au mode release : données de débuggage, instructions qui n'apparaissent dans le code binaire qu'en mode débug (assertion), et bien d'autres choses. Cela ralenti forcément l'exécution du programme
    • Le mode débug peut faire certaines choses que le mode release ne peut pas forcément, comme initialiser (ou réinitialiser) des pointeurs à des adresses spécifiques (voir à null), ajouter des symboles que le débuggeur poura utiliser, ... Tout cela pour permettre au débuggueur de faire son travail et de nous laisser voir "les entrailles" de l'application

    Et, si tu ajoutes là dessus des outils d'analyses dynamique (comme valgring), tu perds encore -- du fait de l'utilisation de l'outil -- un tout petit peu de performances (il faut bien qu'il tienne le compte de toutes les ressources allouées et libérées ).

    Tout cela pour dire que le fait que le symptôme (l'erreur de segmentation) disparaisse en mode debug ou lorsque tu utilises valgrind est justement la preuve que, sans le code, nous ne pourront absolument rien faire.

    Par contre, ce que nous pouvons faire, c'est te donner quelques pistes à explorer par toi-même :
    1. Evites les pointeurs à chaque fois que leur usage n'est pas indispensable : les références (éventuellement) présentent souvent une alternative bien plus sécurisante
    2. Utilises les pointeurs intelligents (std::unique_ptr, std::shared_ptr)chaque fois que possible
    3. Chaque fois que tu écris un delete sur un pointeur, veille à l remettre à NULL (ou plutôt nullptr)
    4. Chaque Avant chaque tentative d'accès à un pointeur, vérifie sa validité en t'assurant qu'il n'est pas égal à NULL (nullptr).
    5. Sois particulièrement attentifs aux pointeurs qui sont référencés par différents éléments... On a vite fait "d'oublier" de mettre l'un des éléments à jour pour indiquer que le pointeur en question a été détruit ou qu'il a "changé de place".
    6. Sépare très clairement la responsabilité qui permet l'utilisation de tes pointeurs de celle qui en permet le maintien. Pas seulement au niveau des fonctions, mais carrément au niveau de classes (ou de structures) différentes : le terme générique "manager" est une catastrophe pour le SRP
    7. J'en oublie surement, mais commence déjà par cela
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Membre averti
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Avril 2014
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2014
    Messages : 35
    Par défaut
    Merci beaucoup pour vos reponses,

    je connais un peu les "segmentation Fault" mais ce qui m'intrigait dans le cas present c'etait le fait qu'elle n'apparaissait pas deux fois au meme moment du programme mais a des moments proches et sur des actions "repetes" (ie. ce n'etait pas logique qu'une action reussisse 1000 fois puis fail sans raison la 1000 et 1eme fois). Dans la plupart des cas, je pouvais voir directement ou etait la faute car le programme plantait toujours au meme endroit et en general c'etait plutot simple.

    En plus c'est sur des bouts de codes de librairies externes (ITK/VTK pour ceux qui connaissent) donc j'avais du mal a croire que le probleme pouvait venir de la...

    Bon j'ai reussi a faire tourner mon code et l'output semble bon, je vais voir plus tard si je peux avoir le fin mot de l'histoire et comprendre pourquoi cela tourne en debug et pas en release...

  8. #8
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Parce que souvent, le mode débug va explicitement mettre à zero toutes les variables.

    Pour moi, une segfault qui disparait en debug, c'est une variable utilisée sans avoir été initialisé.
    surtout s'il n'y a pas de #if DEBUG

  9. #9
    Membre averti
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Avril 2014
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2014
    Messages : 35
    Par défaut
    en fait pour peut-etre donner une idee le programme plante lorsque cette fonction (RequiresInitialization()) de la classe vtkCell est appele pour un sous classe de vtkCell qui est vtkTriangle dans la function "GetCell" de vtkUnstructuredGrid :

    virtual int RequiresInitialization() { return 0;}

    vous pouvez trouver le header complet de la classe (vtkCell) :

    http://www.vtk.org/doc/release/4.0/h...8h-source.html

    et la sous classe est la classe vtkTriangle ici :

    http://www.vtk.org/doc/release/4.0/h...8h-source.html

    et enfin la classe vtkUnstructuredGrid qui contient la function "GetCell" qui apelle la fonction qui plante "RequiresInitialization()" de la classe vtkTriangle herite de vtkClass

    http://www.vtk.org/doc/nightly/html/...8h_source.html

  10. #10
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Tu n’as pas précisé quel est ton environnement.

    Si c’est sous windows, le debugger intégré à visual studio est excellent.

    Si c’est sous linux, tu peux lancer ton programme avec gdb. Par contre, l’interface textuelle de gdb est un peu complexe. Lancer le programme depuis un IDE avec intégration gdb (qt creator, par exemple) est un moyen de rendre cela nettement plus convivial, sinon, il y a pas mal de tutoriels sur l’utilisation de gdb.

    Je doute (mais je ne me prononcerais pas avec certitude) que le problème vienne de la vtk elle-même. Je pense plutôt que tu l’appelles mal à un moment (par exemple, un paramètre null qui ne devrait pas, ou avec une valeur arbitraire).

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    pour crasher dans une vtable, t'aurais pas un cast cavalier qui traine ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  12. #12
    Expert confirmé

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 033
    Billets dans le blog
    12
    Par défaut
    Citation Envoyé par Bousk Voir le message
    pour crasher dans une vtable, t'aurais pas un cast cavalier qui traine ?
    Ou mieux encore, un memset?
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  13. #13
    Invité
    Invité(e)
    Par défaut
    Parce que souvent, le mode débug va explicitement mettre à zero toutes les variables.
    j'ai également déjà eu le cas où il y avait incompatibilité binaire...

    une certaine de tes librairies est compilée avec une certaine version de itk (par exemple),
    puis tu upgrades itk vers une version supérieure.
    Dans cette version supérieure tu as une classe qui est plus bincomp (ajout d'un champ par exemple) mais tu recompiles pas ta librairie.

    et du coup dans ta librairie tu vas charcuter la mémoire, en debug pas de problème, pas d'assertions concernées, mais en release ... BANG

    enfin bref, ca reste que de la spéculation, sans code, c'est un peu du majax

    edit: pas vu le poste de Aujourd'hui, 14h29

Discussions similaires

  1. Segmentation fault incomprehensible
    Par sorry60 dans le forum Réseau
    Réponses: 12
    Dernier message: 10/12/2005, 17h06
  2. [SDL_Image] Img_Load : segmentation fault ....
    Par Mathieu.J dans le forum OpenGL
    Réponses: 6
    Dernier message: 19/10/2004, 23h52
  3. [REDHAT] Segmentation fault systematique
    Par mela dans le forum RedHat / CentOS / Fedora
    Réponses: 2
    Dernier message: 21/09/2004, 06h05
  4. Réponses: 13
    Dernier message: 13/07/2004, 15h41
  5. Comment contrer la "segmentation fault" ?
    Par guillaume_pfr dans le forum C
    Réponses: 15
    Dernier message: 08/08/2003, 13h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo