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 :

Malloc et segmentation fault sous Linux


Sujet :

C

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 15
    Par défaut Malloc et segmentation fault sous Linux
    Bonjour. Je resitue le projet que je dois réaliser : un programme qui doit donner l'arborescence du repertoire racine d'un serveur donné en paramétre, en extraire les fichiers web, scanner les liens et indiquer les liens morts.
    L'astuce consiste à coder un programme fonctionnant sous Windows ET sous Linux.
    Sous Windows, pas de probléme (enfin si, y'en a eu mais ca marche )
    Sous Linux, là, ca marche pas. Aucune erreur à la compilation, même pas un warning sur les 400 lignes de code mais à l'execution, je me prend un trés propre "erreur de segmentation" . J'ai localisé le probléme
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dirent.h> 
    # define MAX 1000
     
    int main(int argc, char *argv[])
    {
    char **tableauRep;
     
    tableauRep=(char**)malloc(MAX*sizeof(char*));
    for (i=0;i<MAX;i++) /* initialisation du tableau qui reccueillera le noms des repertoires*/
        {
        tableauRep[i]=(char*)malloc(300*sizeof(char));
        }
    Je ne met que ce qui me semble essentiel. L'allocation de mémoire ne se fait pas sous Linux. Pourquoi se fait-elle sous Windows sans soucis. Dois je me résoudre à faire un tableau statique ?

  2. #2
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Salut

    Je dirais que le segfault ne se fait pas ici
    Tu accedes peut etre à un indice >= MAX pour tableauRep plus loin dans le code
    Ou sinon, tu depasses qd tu tentes d'ecrire dans un des tableauRep[i]

  3. #3
    Membre éclairé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Septembre 2006
    Messages
    572
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 572
    Par défaut
    quand tu dis que tu as localisé l erreur, c'est à l'aide de printf ou avec un debugger genre gdb ?

    pke gdb, si tu as compilé avec l'option -g, ça te ressort la ligne exacte de ton segfault, et tu peux afficher les valeurs des variables etc

  4. #4
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Il faudrait aussi vérifier le retour de tes malloc, c'est plus prudent et afficher un message en cas d'erreur, là au moins t'est fixé
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 15
    Par défaut
    En fait, l'erreur a p-e lieu en amont. Je donne une partie du code situé avant
    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
     
    printf("Repertoire racine : %s\n",racine);
     
    if (opendir(racine)==NULL)
       {
       printf("Repertoire specifie incorrect :");
       //system("pause");
       exit(EXIT_FAILURE);
       }
    printf("avant alloc");/*test*/
    tableauRep=(char**)malloc(MAX*sizeof(char*));
    for (i=0;i<MAX;i++) /* initialisation du tableau qui reccueillera les noms des repertoires/fichiers*/
        {
        tableauRep[i]=(char*)malloc(300*sizeof(char));
        strcpy(tableauRep[i],racine);
        }
    Je constate que le programme bloque avant même l'allocation puisque "segmentation fault" apparait avant "avant alloc"

    Si le répertoire racine est impossible à ouvrir, tout va bien, la condition d'erreur est vérifiée mais s'il est valide, le programme s'arréte


    PS : je débute en c, je fais avec les moyens du bord, j'ai codé avec devcpp sous Windows et le programme gcc sous Linux. Donc le debogage est assez sommaire

  6. #6
    Membre Expert
    Avatar de Gruik
    Profil pro
    Développeur Web
    Inscrit en
    Juillet 2003
    Messages
    1 566
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juillet 2003
    Messages : 1 566
    Par défaut
    Je constate que le programme bloque avant même l'allocation puisque "segmentation fault" apparait avant "avant alloc"
    Haha, le coup classique
    mets un fflush(stdout); apres le printf() si tu veux etre sur que le printf affiche quelquechose

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 15
    Par défaut
    Héhé, merci, ca s'affiche du coup Vu que je faisais tout mes tests avec un printf et que je me fiais à leur non-apparition, chuis parti pour tout retester...
    Je passerai plus tard dans la journée je crois
    Désolé du dérangement.

  8. #8
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Pour moi, sauf si racine vaut NULL lors la tentative d'ouverture du répertoire, là oui tu peux avoir un segfault. Voir mon test qui tourne impec.

    Il ne faut pas oublier de tester le retour des malloc comme déjà dit, opendir renvoi un pointeur sur la structure DIR, ce que tu n'as pas fait dans ton code, les cast ne sont pas nécessaires, j'espère que tu n'oublies pas non plus de libérer la mémoire allouée dynamiquement et que tu fermes bien ton repertoire s'il est ouvert à la fin de tes tâches ... voilà ta partie de code remaniée dans ce sens:
    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dirent.h> 
     
     
    #define MAX 1000
     
     
    int main(int argc, char *argv[])
    {
       DIR * p_dir = NULL;
       int i = 0;
       char ** tableauRep = NULL;
       char * racine = "/home/franhec/Documents";
     
     
       printf ("Repertoire racine : %s\n", racine);
     
       if ((p_dir = opendir (racine)) == NULL)
       {
          printf ("Repertoire specifie incorrect\n");
          exit (EXIT_FAILURE);
       }
       else
       {
          /* Allocation. */
          tableauRep = malloc (MAX * sizeof (*tableauRep));   
          if (tableauRep != NULL)
          {
             for (i = 0; i < MAX; i++)
             {
                tableauRep[i] = malloc (300 * sizeof (**tableauRep));
     
                if (tableauRep [i] == NULL)
                {
                   printf ("Erreur allocation ...\n");
                }
             }
          }
          else
          {
             printf ("Erreur allocation ...\n");
             exit (EXIT_FAILURE);
          }
     
     
          /* Liberation. */
          for (i = 0; i < MAX; i++)
          {
             if (tableauRep [i] != NULL)
             {
                free (tableauRep[i]);
             }
          }
          free (tableauRep);
          tableauRep = NULL;
     
     
          /* Fermeture du repertoire. */
          closedir (p_dir);
       }
     
     
       return EXIT_SUCCESS;
    }
    Sinon bin ton erreur se situe encore autre part
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    262
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 262
    Par défaut
    Ce code est inutile :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    for (i = 0; i < MAX; i++)
          {
             if (tableauRep [i] != NULL)
             {
                free (tableauRep[i]);
             }
          }
          free (tableauRep);
          tableauRep = NULL;
    Ce code suffit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    free (tableauRep);

  10. #10
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Faux.
    tableauRep est bien un tableau de tableaux alloués, et non un simple tableau à deux dimensions.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Citation Envoyé par toxycyty
    Ce code est inutile :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    for (i = 0; i < MAX; i++)
          {
             if (tableauRep [i] != NULL)
             {
                free (tableauRep[i]);
             }
          }
          free (tableauRep);
          tableauRep = NULL;
    Ce code suffit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    free (tableauRep);
    T'est sûr de ton coup ? Moi je vois bien une allocation pour chaque indice de ton tableau:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
             for (i = 0; i < MAX; i++)
             {
                tableauRep[i] = malloc (300 * sizeof (**tableauRep));
     
                if (tableauRep [i] == NULL)
                {
                   printf ("Erreur allocation ...\n");
                }
             }
    et tout ce qu'on alloue, il faut le libérer explicitement !


    PS : je débute en c, je fais avec les moyens du bord
    Justement, prend note de tout ce qu'on te donnes, si on fait quelque chose, ce n'est surement pas par hasard.
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  12. #12
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    262
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 262
    Par défaut
    Mais vous en etes vraiment sur, la desallocation du pointeur fait que tout eest libere non ? je croyais que cetait different d'une liste chainee
    mais ca metonne vraiment

  13. #13
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    • Une allocation, un free().
    • MAX+1 allocations, MAX+1 free().

    C'est simple, non ?
    C'est comme à Ankh-Morpork : "Un homme, une voix" !
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  14. #14
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    262
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 262
    Par défaut
    en effet vous avez raison
    au temps pour moi
    je suis un noob

  15. #15
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Citation Envoyé par toxycyty
    Mais vous en etes vraiment sur, la desallocation du pointeur fait que tout eest libere non ? je croyais que cetait different d'une liste chainee
    mais ca metonne vraiment
    Bin oui on est sûr de nous à 200% même Relis ton chapitre sur malloc/free
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

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

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par toxycyty
    Ce code est inutile :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    for (i = 0; i < MAX; i++)
          {
             if (tableauRep [i] != NULL)
             {
                free (tableauRep[i]);
             }
          }
          free (tableauRep);
          tableauRep = NULL;
    Ce code suffit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    free (tableauRep);
    Ben non. Apprend le C avant de sortir une c*nnerie.

  17. #17
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 15
    Par défaut
    Bon ok, l'allocation marchait effectivement. L'erreur était située dans une autre fonction. J'ai fait l'erreur de me fier aux printf mais je ne savais pas qu'il fallait parfois forcer l'écriture du flux sortant...

    Bref, ma faute était la suivante (je la laisse pour l'aspect didactique)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    DIR *rep;
    struct dirent *read;
     
    rep = opendir(repertoire);
    if (readdir(rep)==NULL) /* cas d'un fichier et non d'un repertoire*/
          {/*instruction*/
          }
    while (read = readdir(rep)) /* cas d'un répertoire*/
          {/*instructions*/
          }
    Le if était un peu cochon mais ca marchait sous Windows alors ca ne m'avait pas alerté

    Je l'ai remplacé simplement par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    rep = opendir(repertoire);
    if (rep==NULL) /* cas d'un fichier et non d'un repertoire*/
          {/*instruction*/
          }
    while (read = readdir(rep)) /* cas d'un répertoire*/
          {/*instructions*/
          }
    En tout cas merci de vos réponses
    J'ai évité les autres piéges cités (desallocation...)

Discussions similaires

  1. Segment Fault - Sous windows
    Par Reverse_ dans le forum C
    Réponses: 5
    Dernier message: 03/05/2015, 13h30
  2. Erreur segmentation fault sous NS2
    Par kadij dans le forum Développement
    Réponses: 6
    Dernier message: 12/07/2013, 15h07
  3. problème segment fault sur Linux
    Par kerido dans le forum Bibliothèques, systèmes et outils
    Réponses: 2
    Dernier message: 09/07/2013, 11h36
  4. Réponses: 5
    Dernier message: 09/06/2009, 10h30
  5. malloc et segmentation fault
    Par booby dans le forum C
    Réponses: 35
    Dernier message: 11/07/2006, 14h50

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