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 :

pb avec un warning et un segmentation fault


Sujet :

C

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut pb avec un warning et un segmentation fault
    Bonjour, comme le dit le titre du message, je n'arrive pas à me débarrasser de mon warning et d'un segmentation fault. Pourtant le prgm tourne, il me renvoie la bonne valeur, mais tout à la fin j'ai un segmentation fault. J'ai réussi à trouver la ligne de l'erreur.
    Mon prgm est assez simple : il lit un fichier donnees.txt et charge les valeurs dans un tableau. Je vous envoie mon fichier donnees.txt

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    CH3
    12.5 1000.2
    12.3 45.2 10.2 45.3 63.22 78 45.1
    45.0 56.3 78.98 56.32 478.63 56.32 896.3
     
    CH2
    23.2 56.1
    121.2 56.3 25.2 12 63.3 56.3 4102.3
    45.3 65.3 23.3 652.69 78.2 56.3 56.98
    et mon main

    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
     
    #include<stdlib.h>
    #include<stdio.h>
    #include<string.h>
     
    typedef struct {
        char * name; /* name */
        double M;    /* molar mass */
        double Ts;   /* critical temperature */
        double * BT; /* 7 low temperature coefficients */
        double * HT; /* 7 high temperature coefficients */
    } Species_;
     
    typedef Species_ * Species;
    typedef Species * pSpecies;
     
    Species CreateSpecies(char * n,double M_,double Ts_,double * BT_,double * HT_)
    {
        Species s=malloc(sizeof(Species_));
        s->name=n;
        s->M=M_;
        s->Ts=Ts_;
        int i;
        s->BT=malloc(7*sizeof(double));
        s->HT=malloc(7*sizeof(double));
        for(i=0;i<7;++i)
        {
    	s->BT[i]=BT_[i];
    	s->HT[i]=HT_[i];
        }
        return s;
    }
     
    Species CreateEmptySpecies(void)
    {
        Species s=malloc(sizeof(Species_));
        s->name="no name";
        s->M=0.0;
        s->Ts=0.0;
        s->BT=malloc(7*sizeof(double));
        s->HT=malloc(7*sizeof(double));
        int i;
        for(i=0;i<7;++i)
    	s->BT[i]=s->HT[i]=0.0;
     
        return s;
    }
     
    void PrintSpecies(Species s)
    {
        if(s->M==0.0)
    	printf("Empty Species\n");
        else
        {
    	printf("%s\n",s->name);
    	printf("%f\t%f\n",s->M,s->Ts);
    	int i;
    	for(i=0;i<7;++i)
    	    printf("%f\t",s->BT[i]);
    	printf("\n");
    	for(i=0;i<7;++i)
    	    printf("%f\t",s->HT[i]);
    	printf("\n");
        }
        return;
    }
     
    void DestroySpecies(pSpecies s)
    {
        free((*s)->BT);
        free((*s)->HT);
        free(*s);
        return;
    }
     
    void LoadSpecies(char * name_file,char *name_species,double *M,double *T,double * t1,double * t2);
     
    int main()
    {
     
        char * name_file="donnees.txt";
        double M,T;
     
        double * t1=malloc(7*sizeof(double));
        double * t2=malloc(7*sizeof(double));
     
    char * Name[]={"CH3","CH2","CH3"};
        printf("%s\t%s\t%s\n",Name[0],Name[1],Name[2]);
     
        Species tab=malloc(3*sizeof(Species_));
        int i;
        for(i=0;i<3;++i)
        {
    	LoadSpecies(name_file,Name[i],&M,&T,t1,t2);
     
    	tab[i]=*CreateEmptySpecies();
    	tab[i].name=Name[i];
     
    	LoadSpecies(name_file,Name[i],&tab[i].M,&tab[i].Ts,tab[i].BT,tab[i].HT);
     
    	printf("affichage de tab[%d]\n",i);
    	PrintSpecies(&tab[i]);
        }
     
        //free(t1); free(t2);
     
        for(i=0;i<3;++i)
    	DestroySpecies(&tab[i]);
     
        free(tab);
     
        return 0;
    }
     
    void LoadSpecies(char * name_file,char *name_species,double *M,double *T,double * t1,double * t2)
    {
        FILE * file=fopen(name_file,"r");
        if (file==NULL)
        {
    	printf("Error in function LoadSpecies : file %s unfounded\nExit program\n",name_file);
    	exit(1);
        }
     
        /* definition d'un tableau de char destine a recevoir la ligne */
        char line[150];
     
        /* definition d'un compteur de lignes et initialisation */
        int cpt = 1;
     
        /* lecture de la premiere ligne du fichier name_file */
        fgets (line, sizeof line, file);
     
        char *p = strchr(line, '\n'); /* cherche le '\n' */
        if (p != NULL) /* si on l'a trouve, on l'elimine. */
    	*p = 0;
     
     
        int d=strcmp(line,name_species);
     
     
        while( d && (fgets (line, sizeof line, file) != NULL) )
        {
    	++cpt; /* Mise a jour du compteur de lignes */
     
    	p = strchr(line, '\n'); /* cherche le '\n' */
    	if (p != NULL) /* si on l'a trouve, on l'elimine. */
    	    *p = 0;
     
    	d=strcmp(line,name_species);
        }
     
        if (feof(file)) /* la fin de fichier a ete detectee */
        {
    	printf("Error in function LoadSpecies : species %s unfounded\nExit program\n",name_species);
    	//puts("Espece introuvable\nArret du programme\n");
    	exit(1);
        }
     
        /* on charge l'espece */
     
        fscanf(file,"%lf%lf",M,T);
     
        int i;
     
        for(i=0;i<7;++i)
    	fscanf(file,"%lf",&t1[i]);
     
        for(i=0;i<7;++i)
    	fscanf(file,"%lf",&t2[i]);
     
        fclose(file);
     
        return;
    }
    Ma sortie est correct (affichage à l'écran des bonnes valeurs). Voici ce que j'obtiens :

    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
     
    main.c:137: attention : passage de l'argument n°1 de « DestroySpecies » d'un type pointeur incompatible
    CH3     CH2     CH3
    affichage de tab[0]
    CH3
    12.500000       1000.200000
    12.300000       45.200000       10.200000       45.300000       63.220000       78.000000       45.100000
    45.000000       56.300000       78.980000       56.320000       478.630000      56.320000       896.300000
    affichage de tab[1]
    CH2
    23.200000       56.100000
    121.200000      56.300000       25.200000       12.000000       63.300000       56.300000       4102.300000
    45.300000       65.300000       23.300000       652.690000      78.200000       56.300000       56.980000
    affichage de tab[2]
    CH3
    12.500000       1000.200000
    12.300000       45.200000       10.200000       45.300000       63.220000       78.000000       45.100000
    45.000000       56.300000       78.980000       56.320000       478.630000      56.320000       896.300000
    Erreur de segmentation
    Mon erreur vient du tableau tab mais je n'arrive pas à la corriger. Pouvez-vous m'aider ?
    Excusez-moi encore de cette longue lecture.
    Merci.

  2. #2
    Membre habitué Avatar de semaj_james
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    193
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 193
    Points : 139
    Points
    139
    Par défaut
    cette fonction prend en parametre s de type pSpecies

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    void DestroySpecies(pSpecies s)
    {
        free((*s)->BT);
        free((*s)->HT);
        free(*s);
        return;
    }

    et dans le main du lui passe &tab[i] qui est de type species.


    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
     
    int main(void)
    {
     
    Species tab=malloc(3*sizeof(Species_));
     
    DestroySpecies(&tab[i]);
     
     
    }
     
    void DestroySpecies(Species s)
    {
        free(s->BT);
        free(s->HT);
        free(s);
        return;
    }

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    ah. Mais avant toute chose, il y a qqch que je ne comprends pas. Quand j'écris :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Species tab=malloc(3*sizeof(Species_));
    donc tab est un pointeur vers un Species_ (sauf erreur de ma part). Ma question : pourquoi dois-je écrire

    et non

    Enfin, si je fais
    alors, comme tab[i] est un Species (donc un Species_ *) alors &tab[i] est l'adresse d'un Species c'est à dire un pSpecies non ?

    Je pense que je suis en train de m'emmêler les pinceaux parmis tous ces pointeurs.

  4. #4
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par salseropom
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Species tab=malloc(3*sizeof(Species_));
    C'est un peu horrible comme code... On de sait pas ce que sont 'Species' ni 'Species_'

    L'expression 'canonique' est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    T *p = malloc (n * sizeof *p);
    Il n'est pas bon de cacher le pointeur. Le programmeur C est fier de ses pointeurs, il ne les cache pas.
    donc tab est un pointeur vers un Species_ (sauf erreur de ma part). Ma question : pourquoi dois-je écrire
    et non
    Simple. Quel est le type de tab[i] ?

    Voici une version plus claire et sécurisée. Je te demande de l'étudier en détails. Il n'y a rien de compliqué, au contraire.
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
     
    #include<stdlib.h>
    #include<stdio.h>
    #include<string.h>
     
    typedef struct
    {
        char const * name; /* name */
        double M;    /* molar mass */
        double Ts;   /* critical temperature */
        double * BT; /* 7 low temperature coefficients */
        double * HT; /* 7 high temperature coefficients */
    }
    Species;
     
    Species * CreateEmptySpecies(void)
    {
        Species *s = malloc (sizeof * s);
     
        if (s != NULL)
        {
            s->name = "no name";
            s->M = 0;
            s->Ts = 0;
            s->BT = malloc (7 * sizeof *s->BT);
     
            if (s->BT != NULL)
            {
                s->HT = malloc (7 * sizeof *s->HT);
     
                if (s->HT != NULL)
                {
                    int i;
     
                    for(i = 0; i < 7; i++)
                    {
                        s->BT[i] = 0;
                        s->HT[i] = 0;
                    }
                }
                else
                {
                    free(s->BT), s->BT = NULL;
                    free(s), s = NULL;
                }
            }
            else
            {
                free(s), s = NULL;
            }
        }
        return s;
    }
     
    Species *CreateSpecies(char * n
                           ,double M
                           ,double Ts
                           ,double * BT
                           ,double * HT)
    {
        Species *s = CreateEmptySpecies ();
     
        if (s != NULL)
        {
            s->name = n;
            s->M = M;
            s->Ts = Ts;
            {
                int i;
     
                for(i = 0; i < 7; i++)
                {
                    s->BT[i] = BT[i];
                    s->HT[i] = HT[i];
                }
            }
        }
        return s;
    }
     
    static void DestroySpecies(Species *s)
    {
        free(s->BT);
        free(s->HT);
        free(s);
        return;
    }
     
    static void clean(char *line, FILE *file)
    {
        char *p = strchr(line, '\n'); /* cherche le '\n' */
     
        if (p != NULL) /* si on l'a trouve, on l'elimine. */
        {
            *p = 0;
        }
        else
        {
            /* clean up */
            int c;
            while ((c=fgetc(file)) != '\n' && c != EOF)
            {}
        }
    }
     
    static int LoadSpecies(char const *name_file
                           ,char const *name_species
                           ,double *pM
                           ,double *pT
                           ,double * t1
                           ,double * t2)
    {
        int ret=EXIT_SUCCESS;
        FILE * file = fopen (name_file,"r");
     
        if (file != NULL)
        {
            /* definition d'un tableau de char destine a recevoir la ligne */
            char line[128];
     
            /* definition d'un compteur de lignes et initialisation */
            int cpt = 1;
     
            /* on a encore rien trouve... */
            int found = 0;
     
            while (fgets (line, sizeof line, file) != NULL)
            {
                clean (line, file);
     
                if (strcmp (line, name_species) == 0)
                {
                    found=1;
                    break;
                }
                ++cpt; /* Mise a jour du compteur de lignes */
            }
     
            /* la fin de fichier a ete detectee */
            if (found)
            {
                /* on charge l'espece */
     
                int n = fscanf(file,"%lf%lf",pM,pT);
     
                if (n == 2)
                {
                    int i;
     
                    n = 1;
     
                    for(i = 0; i < 7 && n == 1; i++)
                    {
                        n = fscanf(file,"%lf",t1+i);
                    }
     
                    for(i = 0; i < 7 && n == 1; i++)
                    {
                        n = fscanf(file,"%lf",t2+i);
                    }
                }
     
                if (n != 1)
                {
                    printf("Error in function LoadSpecies : error while loading species %s\n"
                           "Exit program\n"
                           ,name_species);
                    ret = EXIT_FAILURE;
                }
            }
            else
            {
                printf("Error in function LoadSpecies : species %s not found\n"
                       "Exit program\n"
                       ,name_species);
                ret = EXIT_FAILURE;
            }
     
            fclose(file), file =NULL;
        }
        else
        {
            printf("Error in function LoadSpecies : file %s not found\n"
                   "Exit program\n"
                   ,name_file);
            ret=EXIT_FAILURE;
        }
        return ret;
    }
     
    static void PrintSpecies(Species *s)
    {
        if (s != NULL)
        {
            if(s->M==0.0)
            {
                printf("Empty Species\n");
            }
            else
            {
                if (s->name != NULL)
                {
                    printf("%s\n",s->name);
                }
                printf("%8.2f%8.2f\n", s->M, s->Ts);
     
                {
                    int i;
     
                    for(i = 0; i < 7;i++)
                    {
                        printf ("%8.2f", s->BT[i]);
                    }
                    printf("\n");
     
                    for(i = 0; i < 7; i++)
                    {
                        printf ("%8.2f", s->HT[i]);
                    }
                    printf("\n");
                }
            }
        }
    }
     
    int main(void)
    {
        static char const name_file[]="data.txt";
        static char const * Name[]=
            {
                "CH3",
                "CH2",
                "CH3",
            };
        printf ("%8s%8s%8s\n", Name[0],Name[1],Name[2]);
     
        {
            /* creation d'un tableau de pointeurs */
            Species ** tab = malloc (3 * sizeof *tab);
     
            if (tab != NULL)
            {
                int i;
     
                for (i = 0; i < 3; i++)
                {
                    tab[i] = NULL;
                }
     
                for (i = 0; i < 3; i++)
                {
                    tab[i] = CreateEmptySpecies();
                    tab[i]->name = Name[i];
                    {
                        int ret =LoadSpecies (name_file
                                              ,tab[i]->name
                                              ,&tab[i]->M
                                              ,&tab[i]->Ts
                                              ,tab[i]->BT
                                              ,tab[i]->HT);
     
                        if (ret==EXIT_SUCCESS)
                        {
                            printf ("affichage de tab[%d]\n", i);
                            PrintSpecies (tab[i]);
                        }
                    }
                }
     
                for (i = 0; i < 3; i++)
                {
                    DestroySpecies(tab[i]);
                }
                free(tab), tab = NULL;
            }
        }
        return 0;
    }
    Ca donne
    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
     
         CH3     CH2     CH3
    affichage de tab[0]
    CH3
       12.50 1000.20
       12.30   45.20   10.20   45.30   63.22   78.00   45.10
       45.00   56.30   78.98   56.32  478.63   56.32  896.30
    affichage de tab[1]
    CH2
       23.20   56.10
      121.20   56.30   25.20   12.00   63.30   56.30 4102.30
       45.30   65.30   23.30  652.69   78.20   56.30   56.98
    affichage de tab[2]
    CH3
       12.50 1000.20
       12.30   45.20   10.20   45.30   63.22   78.00   45.10
       45.00   56.30   78.98   56.32  478.63   56.32  896.30
    Conception : on peut se poser la question du pourquoi de ces tableaux dynamiques, vu qu'ils ont une taille fixe...

    Je comprendrais le tout dynamique si c'est le fichier qui déterminais les tailles, mais là, on en est loin. Pour le moment, c'est plutôt bar=tard comme conception. Mi-fixe, mi-souple...
    Pas de Wi-Fi à la maison : CPL

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    Salut Emmanuel, tu dois sûrement voir que ce message est donc la suite d'un précédent message où tu me parlais des fgets et des fscanf.
    Le progralmeur C est fier de ses pointeurs, il ne les cache pas.
    si je "cache" mes pointeurs, c'est plus pour éviter d'avoir des étoiles qui se trainent un peu partout dans mon code.

    Quel est le type de tab[i] ?
    Comme je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Species tab=malloc(3*sizeof(Species_));
    ce qui revient à faire (avec le typedef)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Species_ * tab=malloc(3*sizeof(Species_));
    alors tab est un pointeur vers un Species_ donc (et oui, là est mon erreur alors), tab[i] est donc un Species_.

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    Bien alors j'ai corrigé mes erreurs en m'inspirant de ce que m'a dit semaj_james. Mon destructeur devient :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    void DestroySpecies(Species s)
    {
        free(s->BT);
        free(s->HT);
        //free(s); <-- cette ligne fait planter mon prgm, pourquoi ?
        return;
    }
    et mon main devient

    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
     
    int main()
    {
     
        char * name_file="donnees.txt";
     
        char * Name[]={"CH2","CH3","CH3"};
        printf("%s\t%s\t%s\n",Name[0],Name[1],Name[2]);
     
        Species tab=malloc(3*sizeof(Species_));
        int i;
        for(i=0;i<3;++i)
        {
    	tab[i]=*CreateEmptySpecies();
    	tab[i].name=Name[i];
     
    	LoadSpecies(name_file,Name[i],&tab[i].M,&tab[i].Ts,tab[i].BT,tab[i].HT);
     
    	printf("affichage de tab[%d]\n",i);
    	PrintSpecies(&tab[i]);
        }
     
        for(i=0;i<3;++i)
    	DestroySpecies(&tab[i]);
     
        free(tab);
     
        return 0;
    }
    tout marche... sauf ma ligne en comentaire de mon destructeur. Mais je trouve très "douteux" la ligne suivante de mon main

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    tab[i]=*CreateEmptySpecies();
    même si ça marche, je trouve que c'est un peu compliqué. Dès que mon prgm tournera, j'expliciterai les étoiles des pointeurs.

    Pouvez-vous donc m'expliquer pourquoi mon destructeur fait planter mon prgm ?
    Merci

  7. #7
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void DestroySpecies(Species s) 
    { 
        free(s->BT); 
        free(s->HT); 
        //free(s); <-- cette ligne fait planter mon prgm, pourquoi ? 
        return; 
    }
    Si j'ai à peu près compris ton code difficle à suivre à cause du masquage des pointeurs (Emmanuel a raison), tu ne peux pas faire de free(s) parce le Species s en question n'a PAS été obtenu par malloc.
    Je m'explique :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Species CreateSpecies(...)
        Species s=malloc(sizeof(Species_)); 
        ...
        return s; 
    }
    La fonction crée par allocation dynamique un Species_ et renvoie son adresse
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      tab[i]=*CreateEmptySpecies();
    Cette adresse est dérérencée et une COPIE de la structure créée par CreateSpecies est stockée dans le tableau. Les éléments du tableau ne sont pas ceux créés par CreateEmptySpecies. Ces derniers sont quelque part en mémoire et on ne sait plus où.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Species tab=malloc(3*sizeof(Species_));
    Tu peux faire un free(tab) mais pas un free sur les éléments de tab
    Il n'est pas logique, et cela amène ton problème, d'avoir un tableau de Species_ , puisque tu veux les construire par allocation dynamique, tu devrait avoir un tableau de pointeurs sur Species_
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  8. #8
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par salseropom
    tout marche... sauf ma ligne en comentaire de mon destructeur. Mais je trouve très "douteux" la ligne suivante de mon main
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    tab[i]=*CreateEmptySpecies();
    Absolument. Ce code est erroné. Diogène a parfaitement expliqué le problème.
    même si ça marche, je trouve que c'est un peu compliqué. Dès que mon prgm tournera, j'expliciterai les étoiles des pointeurs.

    Pouvez-vous donc m'expliquer pourquoi mon destructeur fait planter mon prgm ?
    J'ai posté une version corrigée (à poil!, avec pointeurs explicites (explicit content) un peu plus haut... Si tu as des questions n'hésite pas.
    Pas de Wi-Fi à la maison : CPL

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    135
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 135
    Points : 81
    Points
    81
    Par défaut
    donc tab est un pointeur vers un Species_ (sauf erreur de ma part). Ma question : pourquoi dois-je écrire

    Code:

    tab[i].name


    et non

    Code:

    tab[i]->name


    Enfin, si je fais
    Code:

    &tab[i]
    Tu dois ecrire tab[i].name et non tab[i]->name, car tab est de type pointeur, et lorsque tu met des crochets, tu dereference le pointeur...

    En gros quand tu ecris tab[0].name tu demande le champ nom d'un pointeur sur structure contenu a l'indice 0 de ton tableau. tab doit etre un pointeur *.

    Lorsque tu ecris tab[i]->name tu demandes le champ nom d'un pointeur de pointeur sur structure. tab doit etre un pointeur de pointeur **.

  10. #10
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    Bonjour, merci encore de votre patience, mais là vous m'avez tué.
    Je reprends mon code, dans lequel j'ai bien explicité les pointeurs (les étoiles sont explicites) et ensuite je vous pose mes deux questions (je me suis inspiré du code d'Emmanuel et d'une précédente question sur ce forum)

    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
     
    #include<stdlib.h>
    #include<stdio.h>
    #include<string.h>
    #include<assert.h>
     
    typedef struct {
        char * name; /* name */
        double M;    /* molar mass */
        double T;   /* critical temperature */
        double * BT; /* 7 low temperature coefficients */
        double * HT; /* 7 high temperature coefficients */
    } Species;
     
     
    Species * CreateEmptySpecies(void)
    {
        Species * s=malloc(sizeof(*s));
        assert(s!=NULL);
        s->name="no name";
        s->M=0.0;
        s->T=0.0;
        if(s->BT!=NULL) free(s->BT);
        s->BT=malloc(7*sizeof(*s->BT));
        assert(s->BT!=NULL);
        if(s->HT!=NULL) free(s->HT);
        s->HT=malloc(7*sizeof(*s->HT));
        assert(s->HT!=NULL);
        int i;
        for(i=0;i<7;++i)
    	s->BT[i]=s->HT[i]=0.0;
     
        return s;
    }
     
    Species * CreateSpecies(char * n,double M_,double T_,double * BT_,double * HT_)
    {
        Species * s=CreateEmptySpecies();
        assert(s!=NULL);
        s->name=n;
        s->M=M_;
        s->T=T_;
        int i;
        for(i=0;i<7;++i)
        {
    	s->BT[i]=BT_[i];
    	s->HT[i]=HT_[i];
        }
        return s;
    }
     
    void PrintSpecies(Species * s)
    {
        if(s->M==0.0)
    	printf("Empty Species\n");
        else
        {
    	printf("%s\n",s->name);
    	printf("%f\t%f\n",s->M,s->T);
    	int i;
    	for(i=0;i<7;++i)
    	    printf("%f\t",s->BT[i]);
    	printf("\n");
    	for(i=0;i<7;++i)
    	    printf("%f\t",s->HT[i]);
    	printf("\n");
        }
        return;
    }
     
    void DestroySpecies(Species * s)
    {
     
        free(s->BT);
        free(s->HT);
        free(s);
     
        return;
    }
     
    void LoadSpecies(char * name_file,char *name_species,Species **);
     
    int main()
    {
     
        char * name_file="donnees.txt";
     
        char * Name[]={"CH2","CH3","CH3"};
        printf("%s\t%s\t%s\n",Name[0],Name[1],Name[2]);
     
        Species ** tab=malloc(3*sizeof(*tab));
        int i;
        for(i=0;i<3;++i)
        {                    
    	tab[i]=CreateEmptySpecies();
    	LoadSpecies(name_file,Name[i],&tab[i]);
    	PrintSpecies(tab[i]);
        }
     
        for(i=0;i<3;++i)
    	DestroySpecies(tab[i]);
     
        free(tab);
     
        return 0;
    }
     
    void LoadSpecies(char * name_file,char *name_species,Species **s)
    {
        FILE * file=fopen(name_file,"r");
        if (file==NULL)
        {
    	fprintf(stderr,"Error in file %s line %d in function %s : file %s wasn't found\nExit program\n",__FILE__,__LINE__,__FUNCTION__,name_file);
    	exit(1);
        }
     
        /* definition d'un tableau de char destine a recevoir la ligne */
        char line[150];
     
        /* definition d'un compteur de lignes et initialisation */
        int cpt = 1;
     
        /* lecture de la premiere ligne du fichier name_file */
        fgets (line, sizeof line, file);
     
        char *p = strchr(line, '\n'); /* cherche le '\n' */
        if (p != NULL) /* si on l'a trouve, on l'elimine. */
    	*p = 0;
     
     
        int d=strcmp(line,name_species);
     
     
        while( d && (fgets (line, sizeof line, file) != NULL) )
        {
    	++cpt; /* Mise a jour du compteur de lignes */
     
    	p = strchr(line, '\n'); /* cherche le '\n' */
    	if (p != NULL) /* si on l'a trouve, on l'elimine. */
    	    *p = 0;
     
    	d=strcmp(line,name_species);
        }
     
        if (feof(file)) /* la fin de fichier a ete detectee */
        {
    	fprintf(stderr,"Error in file %s line %d function %s : species '%s' wasn't found in file %s\nExit program\n",__FILE__,__LINE__,__FUNCTION__,name_species,name_file);
    	exit(1);
        }
     
        if (ferror(file)) /* une erreur s'est produite */
    	perror (name_file);
     
        /* species is stored */
     
        (*s)->name=name_species;
     
        fscanf(file,"%lf%lf",&(*s)->M,&(*s)->T);
        int i;
     
        for(i=0;i<7;++i)
            fscanf(file,"%lf",&(*s)->BT[i]);
     
        for(i=0;i<7;++i)
            fscanf(file,"%lf",&(*s)->HT[i]);
     
        fclose(file);
     
        return;
    }
    Emmanuel, j'ai bien repris ton code du "destructeur" (vocabulaire du c++). Je le réécris juste en dessous

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void DestroySpecies(Species * s)
    {
     
        free(s->BT);  
        free(s->HT);
        free(s);
     
        return;
    }
    Dans un précédent post, on m'avait dit que je devais faire plutôt

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void DestroySpecies(Species ** s)
    {
     
        free((*s)->BT);
        free((*s)->HT);
        free(*s);
     
        return;
    }
    car sinon (avec ta version qui était la mienne au début) l'argument est passé par valeur et non par pointeur donc l'arguement n'est pas modifié. Or, toi tu m'as donné ma 1e version, et j'avais fait celle-ci car mon argument est un pointeur c'est-à-dire l'adresse d'une case mémoire (si j'ai bien compris...) et le fait de faire free(s->BT), je libère la mémoire correspondante. Donc si je fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Species * s=CreateEmptySpecies();
    PrintSpecies(s);
    DestroySpecies(s);
    est-ce que ma Species * s est détruite ? où dois-je faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    DestroySpecies(&s); <-- ici j'utilise ma 2e version : DestroySpecies(Species ** s)
    Enfin (et ca termine mon message), pourriez-vous m'expliquer ces quelques lignes issues de ma fonction LoadSpecies.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    (*s)->name=name_species;
     
        fscanf(file,"%lf%lf",&(*s)->M,&(*s)->T);
        int i;
     
        for(i=0;i<7;++i)
            fscanf(file,"%lf",&(*s)->BT[i]);
     
        for(i=0;i<7;++i)
            fscanf(file,"%lf",&(*s)->HT[i]);
    Mon prgm marche, mais je suis incapable d'expliquer ces quelques lignes. j'y suis vraiment allé au pif au mètre en jonglant avec les symboles * & et les parenthèses (très mauvais comme raisonnement).

    J'ai juste mis comme argument dans ma fonction LoadSpecies un Species ** car ainsi je modifie mon argument (en fait c'est un peu la même question qu'entre DestroySpecies(Species * s) et DestroySpecies(Species ** s)

    Merci encore de votre patience, mais je vous assure que j'en apprends des choses avec vos remarques. Merci

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    Bonjour, bon j'ai changé ces quelques lignes affreuses en qq lignes plus simples (et que je comprends)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    s->name=name_species;
     
        fscanf(file,"%lf%lf",&s->M,&s->T);
     
        int i;
     
        for(i=0;i<7;++i)
    	fscanf(file,"%lf",&s->BT[i]);
     
        for(i=0;i<7;++i)
    	fscanf(file,"%lf",&s->HT[i]);
    avec le prototype de ma fonction qui devient

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void LoadSpecies(char * name_file,char *name_species,Species *s)
    avant c'était


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void LoadSpecies(char * name_file,char *name_species,Species **s)
    et mon main devient donc

    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
     
    int main()
    {
     
        char * name_file="therm.dat";
     
        char * Name[]={"CH3","CH4,"CH2"};
     
        Species ** tab=malloc(3*sizeof(*tab));
        int i;
        for(i=0;i<3;++i)
        {                    
    	tab[i]=CreateEmptySpecies();
    	LoadSpecies(name_file,Name[i],tab[i]);
    	PrintSpecies(tab[i]);
    	printf("\n");
        }
     
        for(i=0;i<3;++i)
    	DestroySpecies(tab[i]);
     
        free(tab);
     
        printf("\n");
     
        return 0;
    }
    et cette version marche aussi bien. Donc j'en conclus que je passe en argument Species * s ou Species **s ma variable s sera toujours modifée. Est-ce ceci ?

Discussions similaires

  1. segmentation fault avec wxGLCanvas
    Par Ardeciel dans le forum wxWidgets
    Réponses: 1
    Dernier message: 20/03/2007, 20h13
  2. Probleme de segmentation fault avec sprintf
    Par MathG dans le forum C++
    Réponses: 5
    Dernier message: 14/12/2006, 01h12
  3. Segmentation fault avec glCompressedTexImage2DARB
    Par patbier dans le forum OpenGL
    Réponses: 5
    Dernier message: 12/12/2005, 10h32
  4. sprintf avec gcc4 : Segmentation Fault
    Par stephane_bou dans le forum C
    Réponses: 3
    Dernier message: 26/11/2005, 20h02
  5. Pb segmentation fault avec glutinit()
    Par pipistrelle dans le forum GLUT
    Réponses: 2
    Dernier message: 17/11/2004, 23h17

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