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

Bibliothèques, systèmes et outils C Discussion :

Structures et segmentation fault


Sujet :

Bibliothèques, systèmes et outils C

  1. #1
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2021
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2021
    Messages : 10
    Par défaut Structures et segmentation fault
    Bonjour à tous,

    je suis encore assez nouveau avec les notions de structures et listes chainées. Pour faire simple, j'essaye de donner à une variable les valeurs qui sont dans un tableau (de type int). Le tableau est dans une structure. J'obtiens un petit seg faul, donc j'ai essayé de debugger pour comprendre où était ma faute, et il se trouve qu'elle est dans la boucle if de la fonction display. Je crois que ça viendrait d'un nom/type de structure mal utilisé de ma part. Merci d'avance pour votre aide !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    //structure
        typedef struct Avion_dec Element;
        struct Avion_dec
        {
            var v; // on appelle la struct Avion dans cette structure 
            int tab_dec[4];
            struct Avion_dec *tete;
            struct Avion_dec *suivant;
        };
    J'initialise mon tab_dec[4] dans une autre fonction d'initialisation. Voici ma fonction d'affichage :

    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
     
    void display ()
        {
            int i = 0, variable = 0, numero;
            struct Avion var;
            struct Avion_dec *avion_dec;
     
            initialisation(&avion_dec);
     
            for(i = 0; i <4; i++) 
            { 
                variable = avion_dec->tab_dec[i]; 
                printf("%d - ", variable);
            }
        }

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 600
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 600
    Par défaut
    Bonjour,

    Il n'y a rien de particulier dans ce code. La partie intéressante c'est le code de initialisation(). Que fait cette fonction du pointeur de pointeur qu'elle reçoit?

  3. #3
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2021
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2021
    Messages : 10
    Par défaut
    Rien de particulier, je me contente juste d'initialiser chacune des variables, comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        void initialisation (struct Avion_dec *Avion_dec) 
        {
            Avion_dec->tete = NULL;
            Avion_dec->suivant = NULL;
            int var_numero = 0;
            int tab_dec[4] = {2, 5, 1, 3}; //tableau qui contient les caract de caract_avions(2, 5, 1 et 3)
        }

  4. #4
    Membre émérite
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Par défaut
    Bonjour,
    un bon réflexe serait d'utiliser un debuger mais aussi et surtout un memory profiler qui te donnerait beaucoup plus d'informations sur le lieu et le genre de problèmes que tu rencontres.
    ⇒ essaye valgrind si tu es sous linux par exemple.

  5. #5
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 774
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 774
    Par défaut
    Désolé, c'est les vacances je vais faire bref.

    Mais tu définis 1 pointeur (ligne 6) non initialisé et tu passes son adresse/ son pointeur à la procédure initialisation.
    Donc soit tu ne piges pas les pointeurs, soit tu as été étourdi

    je ne dis rien sur le nommage et les variables non utilisées (tu tâtonnes sûrement )

  6. #6
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 315
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 315
    Billets dans le blog
    5
    Par défaut
    Bonjour.

    Histoire d’ajouter quelques informations.
    Les variables int var_numero; et int tab_dec[4]; sont locales à la fonction initialisation ();. Elles n’existent plus à la sortie de cette dernière.

  7. #7
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2021
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2021
    Messages : 10
    Par défaut
    Citation Envoyé par foetus Voir le message
    Désolé, c'est les vacances je vais faire bref.

    Mais tu définis 1 pointeur (ligne 6) non initialisé et tu passes son adresse/ son pointeur à la procédure initialisation.
    Donc soit tu ne piges pas les pointeurs, soit tu as été étourdi

    je ne dis rien sur le nommage et les variables non utilisées (tu tâtonnes sûrement )
    Pour être honnête, j'ai encore du mal avec l'utilisation des pointeurs, je pense avoir compris la partie théorique, mais l'appliquer dans un programme c'est une autre histoire (en effet je tâtonne beaucoup...) Je vais essayer de voir ce qui cloche et de revoir quelques exemples/tutos sur internet.
    Par rapport aux variables non utilisé, j'avais commencé à coder une condition (mais je l'ai enlevé car je l'avais de toute façon mis en commentaire dans mon code, je ne l'ai pas encore fini) et du coup j'ai oublié de retirer les variables de cette partie

    Citation Envoyé par gerald3d Voir le message
    Bonjour.

    Histoire d’ajouter quelques informations.
    Les variables int var_numero; et int tab_dec[4]; sont locales à la fonction initialisation ();. Elles n’existent plus à la sortie de cette dernière.
    Ha mince je pensais qu'en les initialisant et sachant qu'elles sont dans une structure ça prenait en compte les modifications apportées.. Je vais changer ça de suite, merci à tous !

  8. #8
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2021
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2021
    Messages : 10
    Par défaut
    Citation Envoyé par WhiteCrow Voir le message
    Bonjour,
    un bon réflexe serait d'utiliser un debuger mais aussi et surtout un memory profiler qui te donnerait beaucoup plus d'informations sur le lieu et le genre de problèmes que tu rencontres.
    ⇒ essaye valgrind si tu es sous linux par exemple.
    Je vais me renseigner par rapport à ça (car je code sous windows) merci pour l'astuce

  9. #9
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 600
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 600
    Par défaut
    Et il faudrait activer et lire les warnings de compilateur. Beaucoup des erreurs ici doivent t'être signalées par des warnings.

  10. #10
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2021
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2021
    Messages : 10
    Par défaut
    Citation Envoyé par dalfab Voir le message
    Et il faudrait activer et lire les warnings de compilateur. Beaucoup des erreurs ici doivent t'être signalées par des warnings.
    Je les ai déjà d'activés, mais je ne comprenais pas vraiment ce que je pouvais changer vu qu'il m'indique que ce sont des doubles pointeurs
    Nom : init.png
Affichages : 274
Taille : 30,7 Ko

  11. #11
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 600
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 600
    Par défaut
    Tu passes un pointeur de pointeur à une fonction qui attend un pointeur, c'est donc une erreur signalée. N'ayant pas la fonction et voyant que tu passais l'adresse d'un pointeur non initialisé, c'est pourquoi j'ai demandé la fonction qui aurait pu initialiser le pointeur avec de la mémoire dynamique.
    Note que si tu corriges en enlevant le &, tu t'approches d'une solution, mais le compilateur d'indiquera alors l'utilisation d'une variable non initialisée qu'il faut corriger.

    Il y a des choses bizarres avec ton var qui est un type dans Avion_dec et est utilisé comme variable reliée à rien dans main().

  12. #12
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2021
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2021
    Messages : 10
    Par défaut
    Citation Envoyé par dalfab Voir le message
    Tu passes un pointeur de pointeur à une fonction qui attend un pointeur, c'est donc une erreur signalée. N'ayant pas la fonction et voyant que tu passais l'adresse d'un pointeur non initialisé, c'est pourquoi j'ai demandé la fonction qui aurait pu initialiser le pointeur avec de la mémoire dynamique.
    Note que si tu corriges en enlevant le &, tu t'approches d'une solution, mais le compilateur d'indiquera alors l'utilisation d'une variable non initialisée qu'il faut corriger.

    Il y a des choses bizarres avec ton var qui est un type dans Avion_dec et est utilisé comme variable reliée à rien dans main().
    D'accord, merci pour les remarques je vais corriger et revoir mes variables

  13. #13
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 774
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 774
    Par défaut
    On passe 1 pointeur pour modifier 1 variable : donc tu n'as pas besoin de définir 1 pointeur, juste 1 variable de ta structure, et tu passes son adresse pour l'initialiser.
    1 double pointeur est utilisé pour initialiser la structure mais surtout allouer ("malloc"er) le pointeur.

  14. #14
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 845
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 845
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par megumi01 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    struct Avion var
    struct Avion_dec *avion_dec;
     
    initialisation(&avion_dec);
    avion_dec étant de type "struct Avion_dec étoile" (c'est bien déclaré ainsi), &avion_dec est donc de type "struct Avion_dec étoile étoile" (principe simple, tout pointeur de type "truc" devient automatiquement et irrévocablement "truc étoile", quel que soit ce qui est inclus dans le terme "truc").

    Reprends les bases d'une variable. Tu veux un int, tu écris simplement int toto. Tu veux un float, tu écris tout aussi simplement float tutu. Et dans tous les cas tu peux effectivement passer leur adresse à des fonctions de modification, exemple scanf("%d %f", &toto, &tutu).
    Tu peux aussi travailler à partir de pointeurs. C'est pas interdit. C'est idiot, mais c'est pas interdit. Exemple
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int *toto;
    toto=malloc(sizeof(int));
    if (toto == NULL) {
    	// Souci d'allocation, gérer le cas (et généralement ça se traduit par l'arrêt de la fonction sans oublier la libération de toutes les ressources éventuellement allouées en amont)
    	...
    }
    scanf("%d", toto)

    Donc soit tu passes par la notation "pointeur" et dans ce cas tu fais les choses complètement et correctement (tu lui alloues de la mémoire, tu testes le résultat de l'allocation) puis tu passes juste le pointeur à la fonction "initialisation()" ; soit tu utilises la notation "variable normale" et dans ce cas tu supprimes cette étoile idioteincompréhensible à la déclaration. D'autant plus que tu l'as fait pour "var", je ne comprends pas pourquoi tu ne l'as pas fait de façon identique pour "avion_dec".

    Citation Envoyé par megumi01 Voir le message
    mais je ne comprenais pas vraiment ce que je pouvais changer vu qu'il m'indique que ce sont des doubles pointeur
    Effectivement, comme je l'ai dit, ayant déclaré "avion_dec" comme étant un pointeur, "&avion_dec" devient fatalement un double pointeur. Le compilateur ne pouvant pas présumer que "avion_dec" avait été mal déclaré, il te prévient que le paramètre de la fonction "initialisation()" n'est pas prévu pour recevoir un double pointeur.

    Citation Envoyé par megumi01 Voir le message
    Pour être honnête, j'ai encore du mal avec l'utilisation des pointeurs, je pense avoir compris la partie théorique, mais l'appliquer dans un programme c'est une autre histoire (en effet je tâtonne beaucoup...)
    https://www.developpez.net/forums/d2...sion-pointeurs
    Sinon une règle d'or et intransigible: dès que tu as un pointeur, style int *pt ("int" ou tout autre type peu importe), tu n'as absolument pas le droit de modifier le pointé "étoile pt" (donc écrire *pt=...) si tu n'as pas écrit quelque part au dessus "pt=adresse_valide". Le vocable "adrese_valide" peut être une adresse venue d'une autre variable existante (ex int toto; int *pt; pt=&toto => règle respectée j'ai bien écrit "pt=adresse_valide" car "&toto" est bien une adresse existante) ou bien une adresse donnée par malloc (malloc étant une fonction destinée à allouer de la mémoire en live depuis la mémoire disponible de ton ordi). Et si le pointeur est un paramètre de fonction alors la règle reste la même sauf qu'il faut la remonter à l'endroit où on appelle la fonction.
    Tant que tu te forceras à respecter cette règle, tu n'auras aucun problème. Et si tu n'arrives pas à trouver quoi mettre dans "pt", c'est alors peut-être un signe que dans ce cas il ne fallait pas utiliser un pointeur.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  15. #15
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2021
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2021
    Messages : 10
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    https://www.developpez.net/forums/d2...sion-pointeurs
    Sinon une règle d'or et intransigible: dès que tu as un pointeur, style int *pt ("int" ou tout autre type peu importe), tu n'as absolument pas le droit de modifier le pointé "étoile pt" (donc écrire *pt=...) si tu n'as pas écrit quelque part au dessus "pt=adresse_valide". Le vocable "adresse_valide" peut être une adresse venue d'une autre variable existante (ex int toto; int *pt; pt=&toto => règle respectée j'ai bien écrit "pt=adresse_valide" car "&toto" est bien une adresse existante) ou bien une adresse donnée par malloc (malloc étant une fonction destinée à allouer de la mémoire en live depuis la mémoire disponible de ton ordi). Et si le pointeur est un paramètre de fonction alors la règle reste la même sauf qu'il faut la remonter à l'endroit où on appelle la fonction.
    Tant que tu te forceras à respecter cette règle, tu n'auras aucun problème. Et si tu n'arrives pas à trouver quoi mettre dans "pt", c'est alors peut-être un signe que dans ce cas il ne fallait pas utiliser un pointeur.
    Super merci beaucoup pour tes exemples (qui sont très clairs), je vais de ce pas lire ce qui a été dit au lien que tu m'as envoyé

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

Discussions similaires

  1. Structures, pointeur et segmentation fault
    Par pierre_92 dans le forum Langage
    Réponses: 3
    Dernier message: 14/12/2017, 16h01
  2. Segmentation fault sur destruction d'une structure
    Par User Name dans le forum Débuter
    Réponses: 9
    Dernier message: 30/03/2011, 15h31
  3. Réponses: 3
    Dernier message: 21/01/2008, 14h38
  4. Réponses: 6
    Dernier message: 01/11/2007, 18h44
  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