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 :

Erreur de segmentation aléatoire


Sujet :

C++

  1. #1
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut Erreur de segmentation aléatoire
    Bonjour à tous,
    Je bute sur un problème assez bizarre: lors de l'exécution de mon programme, j'obtiens parfois une erreur de segmentation.

    Première initiative, je lance mon application en debug (gdb/eclipse). Je trouve d'où vient l'erreur de segmentation, du moins sur quelle partie du code elle pointe mais je n'arrive pas à la reproduire à tous les coups....
    Bien évidemment, je lance mon programme avec toujours les mêmes paramètres.

    Seconde initiative, je lance l'application avec valgrind pour voir si j'ai des problèmes de mémoire. J'obtiens des erreurs styles " Invalid read of size 8" et "Address 0xc244920 is 16 bytes before a block of size 3,200 alloc'd".
    Je les interprète de la manière suivante: impossible de lire les données.
    Cependant, même avec ces erreurs, il n'y a pas d'erreur de segmentation.
    Je suis complètement perdu.

    Avez-vous déjà rencontrer des problèmes similaires?

    Quelle méthodes utilisez-vous pour les résoudre?

    Merci d'avance!

  2. #2
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Je dirais: utilisation d'un pointeur non initialisé. Parfois, ça tombe dans l'espace d'adressage du programme => pas de segfault. Parfois, ça tombe en dehors => segfault.

  3. #3
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Donc, je dirais examine les pointeurs utilisés dans la section de code incriminée (parlant de valgrind je suppose que tu es en environnement *nix, compiles-tu avec les informations de debug (option -g pour gcc) pour avoir la localisation la plus fine possible dans les rapports de valgrind?).
    Un pointeur doit être utilisé sans initialisation, ou alors tu utilises un index négatif sur un tableau, ce qui a les mêmes effets.

    EDIT: eclipse/gdb --> utilises-tu les options de compilation avec symboles de débuggage pour y voir plus clair? Normalement ça devrait te donner un numéro de ligne dans le source!

  4. #4
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Merci pour ta réponse super rapide.
    Je suis bien sur Linux, et j'ai compilé mon application en debug.

    Je viens de remarquer que la bibliothèque C que j'appelle (où il y a l'erreur de segmentation), fais un truc du style:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mystruct* f = malloc(n, sizeof(mystruct))
    Sans faire de cast (mystruct*).

    Je suis entrain de relancer les tests mais c'est un peu long.

    EDIT: aucun changement, toujours une erreur de compilation.

  5. #5
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Que devient ce pointeur APRES? un malloc peut renvoyer NULL si échec d'allocation==> si utilisé sans tester, on déclenche une segfault.

  6. #6
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Citation Envoyé par therwald Voir le message
    EDIT: eclipse/gdb --> utilises-tu les options de compilation avec symboles de débuggage pour y voir plus clair? Normalement ça devrait te donner un numéro de ligne dans le source!
    Oui oui, j'ai trouvé d'où venais l'erreur, ainsi que la ligne. Mais le code est un peu confus donc pour lire où se trouve l'initialisation (même avec toutes les recherches fournies par eclipse...) est un peu difficile.

    Edit: Le pointeur est testé pour savoir s'il est null ou pas après le malloc. S'il est null on renvoie une erreur.

  7. #7
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Bonjour,
    Je suis toujours bloqué sur la même erreur de segmentation.

    Je voulais voir à quel moment mon pointeur tape sur une zone mémoire incorrect. Pour cela, j'ai fait un compteur et j'ai regardé si on dépasse notre zone mémoire ou pas.

    J'ai remarqué quelques choses de troublant: on dirait que mon programme s'exécute sur plusieurs threads... alors qu'il n'est pas du tout parallélisé (pas de pthread, thread, mpi ou autre chose dans le genre)!
    Lorsque je compile (avec gcc/g++), je ne vois pas d'options de parallélisme.

    Avez-vous déjà rencontrer ce genre de problème?

    Merci d'avance

  8. #8
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    sinon, on pourrait avoir :

    -la réponse du compilateur (mêmes les warnings), mais apparemment ça compile.
    -la pile d'appel et les messages de gdb
    -la fonction, ou la portion de code dans laquelle se trouve l'instruction foireuse


    ça pourrait aider à t'aider.

    Cordialement,


    Edit : parrallélisme : qu'est-ce qui te fais dire ça ? tu vois 2 processus dans le gestionnaire des taches ?

  9. #9
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Merci pour ta réponse.

    Pour la compilation, il y a "seulement" des warnings de variables non utilisées.

    Pour la pile d'appel:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    Program received signal SIGSEGV, Segmentation fault.
    merge (a=0x7fffffffba70, h=0x2432530, no=125) at bouknap.c:531
    531	    if (i->wsum <= j->wsum + w) {
    (gdb) bt
    #0  merge (a=0x7fffffffba70, h=0x2432530, no=125) at bouknap.c:531
    #1  0x00000000006bb334 in multiply (a=0x7fffffffba70, h=0x2432530, x=-125, side=1)
        at bouknap.c:568
    #2  0x00000000006bc808 in callbouknap (n=100, p=0x23896b0, w=0x246bf40, m=0x246c0e0, x=0x246c280, c=187)
        at bouknap.c:902
    #3  0x000000000053f0ce in IntKnapsackSubProblem::customizedSolver (this=0x215d9d0, flag=@0x7fffffffcdee, ifPrint=@0x7fffffffcded, 
        requiredStatus=..., objVal=..., primalBound=..., dualBound=..., inPrimalSol=std::set with 0 elements, inDualSol=
        std::set with 0 elements)
        at hscpSubProblemC.cpp:157
    #4  0x000000000058a1c3 in MipProblem::solveProb (this=0x215d9d0, flag=@0x7fffffffcdee, ifPrint=@0x7fffffffcded)
        at bcProblemC.cpp:3365
    #5  0x000000000059f393 in ColGenSpConf::solvePC (this=0x226f280)
        at /home/rleguay/Projets/bapcodproject/trunk/Bapcod/src/bcColGenSpConfC.cpp:930
    #6  0x00000000005a3462 in ColGenSpConf::genNewCol (this=0x226f280, vectOfNewColumns=std::vector of length 0, capacity 0)
        at bcColGenSpConfC.cpp:1805
    #7  0x00000000005b5a30 in MasterConf::genNewColumns (this=0x22f6260, vectOfNewColumns=std::vector of length 0, capacity 0)
        at bcMasterConfC.cpp:1796
    #8  0x00000000005b6ead in MasterConf::solveMastLpPrimPh2 (this=0x22f6260, nbCgIterations=@0x7fffffffd4dc, start=...)
        at bcMasterConfC.cpp:2121
    #9  0x00000000005b7961 in MasterConf::solveMastLpPrimPh1A2 (this=0x22f6260)
        at bcMasterConfC.cpp:2288
    #10 0x00000000005b964a in MasterConf::solveLagrangianDual (this=0x22f6260)
        at bcMasterConfC.cpp:2835
    #11 0x00000000005bb4e4 in MasterConf::solveCurNodeProblem (this=0x22f6260)
        at bcMasterConfC.cpp:3174
    #12 0x00000000005baf69 in MasterConf::treatCurrentNode (this=0x22f6260)
        at bcMasterConfC.cpp:3092
    #13 0x00000000005b01f5 in MasterConf::solvePC (this=0x22f6260)
        at bcMasterConfC.cpp:759
    #14 0x00000000005e4bcf in Model::solve (this=0x7fffffffdbe0)
        at bcModelC.cpp:225
    #15 0x000000000054e5b7 in main (argc=1, argv=0x7fffffffe248)
        at hscpMain.cpp:97
    Pour la portion de code: (désolé pour ce code dégueulasse mais je n'ai pas le droit de le modifier....)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     for (i = r1, j = r1; (i != m) || (j != m); ) { //i, r1, j et m sont des pointeurs sur un même type de structure. i et j sont des pointeurs sur le début d'une liste et m est sensé être le pointeur sur la fin de la liste.
        if (i->wsum <= j->wsum + w) {
         //... Traitement
         i++;
        }
        else {
         j++;
       }
    }
    Je trouve ce code difficile à lire et en plus dangereux: on fait un test d'arrêt à partir d'un pointeur sans test de savoir si ce pointeur est nul ou pas...


    Pour ce qui est des threads, j'ai déduit ceci quand j'exécute l'application avec gdb je vois:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [New Thread 0x7ffff5526700 (LWP 17654)]
    [Thread 0x7ffff5526700 (LWP 17654) exited]
    [New Thread 0x7ffff5526700 (LWP 17655)]
    [Thread 0x7ffff5526700 (LWP 17655) exited]
    [New Thread 0x7ffff5526700 (LWP 17656)]
    [Thread 0x7ffff5526700 (LWP 17656) exited]
    [New Thread 0x7ffff5526700 (LWP 17657)]
    [Thread 0x7ffff5526700 (LWP 17657) exited]
    [New Thread 0x7ffff5526700 (LWP 17658)]
    [Thread 0x7ffff5526700 (LWP 17658) exited]
    //...

  10. #10
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    Premièrement, tu devrais éviter de laisser tes chemins (trunk/blablabla) en clair si tu es sur un projet professionnel.

    Duexièmement, comme le dit la pile d'appel,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if (i->wsum <= j->wsum + w)//là tu as un problème
    je dirais plus précisément et d'instinct sur le j->wsum + w, mais bien sur tout dépend de ce que sont les membres wsum
    et w (type, etc)

  11. #11
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Citation Envoyé par Kaamui Voir le message
    Premièrement, tu devrais éviter de laisser tes chemins (trunk/blablabla) en clair si tu es sur un projet professionnel.
    Merci du conseil. Je viens de le changer.

    Citation Envoyé par Kaamui Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if (i->wsum <= j->wsum + w)//là tu as un problème
    je dirais plus précisément et d'instinct sur le j->wsum + w,
    Oui je sais où se trouve l'erreur c'est au niveau du i->wsum et non du j. Mais je n'arrive pas à comprendre comment ce paramètre est initialisé.
    Je vais regarder plus en profondeur et si possible contacter le codeur de cette lib.

    Je vous tiens au courant dès que j'ai résolu ce problème.

    Encore merci pour l'aide.

  12. #12
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    Ok, juste par curiosité, quel est le type de wsum ? c'est un entier ? si c'est le cas, alors oui cherche du coté de l'initialisation de wsum à travers i.

    Sinon, j'avais oublié pour l'histoire du multi-thread. Le mot thread est utilisé mais ne veut pas dire que tu as plusieurs thread (multi-thread)

    Ton programme s'éxécute sous forme d'un processus, ce processus peut contenir 1 ou plusieurs threads (des processus légers), et dans ton cas tu voit bien qu'il n'y a qu'un seul thread (regarde les adresses de ce fameux thread, ce sont toutes les mêmes).

    Je ne suis pas suffisamment éclairé à ce niveau (bas) donc je laisse le soin aux autres membres, experts, de me corriger dans mes termes ou dans mes dires.

    Pour plus d'info sur ce qu'est un thread, tu as cet article wiki si tu veux

    Cordialement,

  13. #13
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Le type de wsum est un typedef long donc un longSinon merci pour cette histoire de thread! Je ne me suis focalisé que sur la notion de thread mais pas sur les adresses...

  14. #14
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    quand i atteint la fin de la liste m, on rentre quand même dans la boucle tant que j ne l'a pas atteinte. D'où un adressage invalide. Problème symétrique avec j. Il faut remplacer le test || par un test && :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for (i = r1, j = r1; (i != m) && (j != m); )
    Ce code sera toujours suspect pour 2 raisons :
    => il y a plusieurs variables de boucles
    => les variables de boucle sont modifiées dans la boucle
    => le test de la boucle for est double.

  15. #15
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    ca devrait pas etre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    mystruct* f = malloc(n * sizeof(mystruct))
    ???

  16. #16
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Merci pour vos réponses.

    @3DArchi: Je suis tout à fait d'accord avec toi. Malheureusement, je ne suis pas libre de virer corriger ce code. J'ai quand même tenté de faire ta modification mais aucun changement malheureusement.

    @Joel F: tu as tout à fait raison. J'ai fais un copier coller d'une fonction qui prenais deux paramètres en entrée pour allouer la structure.

    Je sens que je vais devoir re-développer ce code parce que je n'ai aucune nouvelle du créateur.

    Merci quand même pour votre aide.

  17. #17
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Je ne connais pas ton contexte de travail, ni ce que fait cette lib que tu appelles, mais avec l'échantillon de code qu'on a vu tu devrais avoir de bons arguments pour changer de lib. Peut-être trouver une autre lib offrant la même fonctionnalité (généralement plus sûr en terme de coût et fiabilité d'utiliser une lib *de bonne qualité* que de ré-implémenter)?

  18. #18
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2010
    Messages
    517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 517
    Points : 718
    Points
    718
    Par défaut
    Mon contexte de travail est clair: je travaille dans la recherche avec des matheux qui ne savent pas trop coder. Donc je dois jouer un peu à l'arbitre et doit nettoyer le code (il y a plein de variable globale de partout...).
    Le code que je dois remplacer est très ancien (plus de 12 ans.....) donc il faut que j'arrive à convaincre l'ensemble de l'équipe à ne plus utiliser du code non maintenue.
    Je vais voir si une lib équivalente existe.

    Merci pour tout

Discussions similaires

  1. Erreurs de segmentation !
    Par anti-conformiste dans le forum Applications et environnements graphiques
    Réponses: 16
    Dernier message: 18/10/2005, 11h11
  2. Erreur de segmentation
    Par Trunks dans le forum C
    Réponses: 3
    Dernier message: 06/10/2005, 18h28
  3. Erreur de segmentation (Inconnue)
    Par Dark-Meteor dans le forum C
    Réponses: 5
    Dernier message: 08/09/2005, 13h42
  4. [Dev-C++] Erreur de segmentation...
    Par sas dans le forum Dev-C++
    Réponses: 11
    Dernier message: 26/03/2005, 14h25
  5. erreur de segmentation
    Par transistor49 dans le forum C++
    Réponses: 10
    Dernier message: 15/03/2005, 11h18

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