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 :

Optimisation dans gcc -> erreur de segmentation


Sujet :

C

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 20
    Points : 11
    Points
    11
    Par défaut Optimisation dans gcc -> erreur de segmentation
    Bonjour à toutes et tous,

    J'ai une colle à vous poser : je suis sur linux, mon code compile correctement sans et avec optimisation. Par contre, avec optimisation j'ai une erreur de segmentation quand je veux affecter une valeur à une variable de type pile. Une amie Windowsienne qui bosse sur le même projet peut optimiser son code (option dans Code::Blocks) sans erreur de segmentation...

    La structure en question :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    typedef struct step_str
    {
        ushort content;
        int i;
        int j;
        struct step_str *previous;
    }step;
    Le bout de code qui pose apparemment problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ...
     step pr={grid[i][j],i,j};
    ...
    Chose étonnante, quoi que je mette à la place de grid[i][j] j'ai un problème. Deuxième chose étonnante, c'est que même si je créé la variable et affecte les valeurs une par une ensuite j'ai ce problème...

    Pourquoi avec optimisation mon programme plante ? Pourquoi pas sans optimisation ?

    Merci de me filer des idées, j'en suis à court.

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 392
    Points : 23 721
    Points
    23 721
    Par défaut
    Citation Envoyé par nuwanda03 Voir le message
    Le bout de code qui pose apparemment problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ...
     step pr={grid[i][j],i,j};
    ...
    Quand tu fais ceci, tu n'initialises que trois membres : « content », « i » et « j ». Le pointeur « previous », lui, reste indéterminé (ou mis à zéro par le jeu des initialisations).

    D'autre part, en procédant de cette façon, tu déclares une variable locale, qui disparaîtra donc à la fin du bloc courant. C'est très bien comme ça mais si tu affectes son adresse mémoire au champ « previous » d'une autre instance de « step », ou de quoi que ce soit d'autre, alors cette référence deviendra caduque dès la fin de ton bloc puisque l'objet pointé aura cessé d'exister.

    Pourquoi avec optimisation mon programme plante ? Pourquoi pas sans optimisation ? Merci de me filer des idées, j'en suis à court.
    Parce qu'il s'agit d'un bug intermittent qui « tombe en marche ». Tant que tu restes à peu près dans un segment de mémoire qui t'est alloué, ton programme ne déclenche aucune segfault même si tu écrases joyeusement tout ce qui est autour de toi. Dès que tu en sors, par contre…

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 20
    Points : 11
    Points
    11
    Par défaut
    Tout d'abord, merci pour la réponse !

    Ensuite, voilà un bout de code :
    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
    step* push(step **s, step p)
    {
        step *temp=malloc(sizeof(step));
        if (!temp)
    	exit(1);
        temp->content=p.content;
        temp->i=p.i;
        temp->j=p.j;
        temp->previous=*s;
        *s=temp;
        return *s;
    }
     
    step* pop(step **s)
    {
        if (*s)
        {
    	step *t=*s;
    	*s=(*s)->previous;
    	free(t);
        }
        return *s;
    }
    Donc step pr={grid[i][j],i,j}; ne pose pas de problème puisque je copie son contenu dans une autre variable nommée stack , et je me moque donc royalement de la valeur de previous. Ça a été implémenté comme ça, ce n'est peut-être pas très judicieux, et je vais d'ailleurs essayer de changer ça. Mais ça veut aussi dire que le problème ne vient pas de là.

    Parce qu'il s'agit d'un bug intermittent qui « tombe en marche ».
    J'ai du mal à comprendre... Que vient faire l'optimisation là dedans ?

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 392
    Points : 23 721
    Points
    23 721
    Par défaut
    Citation Envoyé par nuwanda03 Voir le message
    Donc step pr={grid[i][j],i,j}; ne pose pas de problème puisque je copie son contenu dans une autre variable nommée stack , et je me moque donc royalement de la valeur de previous. Ça a été implémenté comme ça, ce n'est peut-être pas très judicieux, et je vais d'ailleurs essayer de changer ça. Mais ça veut aussi dire que le problème ne vient pas de là.
    Merci pour le code mais le problème ne semble pas venir de cette partie. Il faudrait qu'on voie le reste.

    Pour « previous », tu fais une liste chaînée : même si tu remplaces immédiatement ce champ par l'adresse du maillon précédent, il reste que cette chaîne possédera toujours un premier maillon qui, lui, ne référencera rien d'autre. Et si « previous » n'a pas été proprement initialisé, il n'y a aucun moyen de détecter l'extrémité de la chaîne.

    Est-ce que ça change quelque chose si tu écris « step pr={grid[i][j],i,j,NULL}; » ?

    J'ai du mal à comprendre... Que vient faire l'optimisation là dedans ?
    Par définition, un code optimisé est différent du code original et donc, les effets de bords peuvent s'en trouver modifiés eux-aussi si tu as des cas de figures indéfinis dans ton code.

    Il est tout-à-fait possible, par exemple, que dans le cas normal, « previous » soit implicitement mis à zéro, ce qui est interprété ensuite comme un « NULL » par le reste de ton code mais qu'en mode optimisé, le compilateur s'épargne la peine de renseigner ce champ s'il s'aperçoit que tu ne l'utilises jamais, en tout cas pas dans le bloc où tu instancies ta structure.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 20
    Points : 11
    Points
    11
    Par défaut
    La variable stack est déclarée dans le main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    step* stack=NULL;
    game(gridFilled,gridUser,mask,sizeGrid,stack);
    Puisque stack est égale à NULL, ma fin de pile est bien délimitée, non ? Ensuite je passe ma variable dans la fonction game(), et un petit push(&stack,pr); me permet de rajouter le contenu de pr à ma pile.

    Et step pr={grid[i][j],i,j,NULL}; ne donne pas mieux. De toute façon je ne récupère pas previous, donc peu importe sa valeur.

    PS : je confirme que sur Windows 32 et 64 bits ça fonctionne avec optimisation (sur Code::Blocks à chaque fois). Apparemment gcc est en version 4.7.1 sur Windows, et 4.7.2 sur ma Debian.

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 20
    Points : 11
    Points
    11
    Par défaut
    Je peux voir avec gdb que certaines de mes variables sont <optimized out>. Et mes erreurs de segmentation semblent venir de l'accès à ma grille a cause de ces variables dont je ne peux pas connaître la valeur.

    SetBit(grid[row][column], bit); est maintenant la source du problème. Ici row=0, colum et bit sont <optimized out>...

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 20
    Points : 11
    Points
    11
    Par défaut
    Erreur décelée : je récupérais l'adresse d'une variable locale dont la mémoire était désallouée avant que je ne fasse mon push()... Sans optimisation, peut-être que la mémoire était désallouée plus tard (ou bien le compilateur corrigeait mon erreur ?), mais avec c'était l'erreur de segmentation.

    Merci bien Obsidian, mine de rien tu m'as fait cherché dans la bonne direction.

  8. #8
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 392
    Points : 23 721
    Points
    23 721
    Par défaut
    Citation Envoyé par nuwanda03 Voir le message
    Erreur décelée : je récupérais l'adresse d'une variable locale dont la mémoire était désallouée avant que je ne fasse mon push()... Sans optimisation, peut-être que la mémoire était désallouée plus tard (ou bien le compilateur corrigeait mon erreur ?), mais avec c'était l'erreur de segmentation.
    En fait, c'est surtout dû au fait que le système t'alloue de la mémoire par pages assez grandes et que malloc() les gère ensuite au mieux. Si tu accèdes à une variable désallouée mais qui se trouvait au sein d'une page qui est toujours à toi, alors le système ne déclenchera pas de segfault.

    Merci bien Obsidian, mine de rien tu m'as fait cherché dans la bonne direction.
    Merci à toi d'avoir d'être venu marquer le sujet comme résolu.
    Bon courage pour la suite.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 7
    Dernier message: 12/05/2010, 15h33
  2. Réponses: 1
    Dernier message: 21/10/2009, 10h36
  3. Réponses: 1
    Dernier message: 11/03/2009, 15h09
  4. Erreur de segmentation dans un thread
    Par Littlepea dans le forum wxWidgets
    Réponses: 3
    Dernier message: 27/06/2008, 19h18
  5. Gcc scanf et erreur de segmentation
    Par titor dans le forum C
    Réponses: 1
    Dernier message: 27/10/2005, 19h27

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