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 :

Segmentation fault; pas d'idées


Sujet :

C++

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

    Informations forums :
    Inscription : Octobre 2011
    Messages : 18
    Par défaut Segmentation fault; pas d'idées
    Bonjour,

    J'ai plus d'idées pour mon problème.

    Merci pour votre aide.

    Y a-t-il quelque chose qui justifie une erreur de segmentation ?


    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
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    main()
    {
    int i=1,j=1;
    char *c2,*c3;
    char *c;
     
    c=0;
     
    c2=0;
    c3=0;
     
    char *a[65000][256];
    for(i=1;i<=65000;i++) {for(j=1;j<=256;j++)*a[i][j]=0;};
     
    i=1;
    j=1;
     
    FILE *fp=fopen("/sdcard/GDE.Main/tt.txt","a+");
    rewind(fp);
    do{
     
    fgets(c,1,fp);
    fseek(fp,1,SEEK_CUR);
    fgets(c2,1,fp);
     
     
    fseek(fp,-1,SEEK_CUR);
     
    if (c=="/t") j++;
    if (c=="/" && c2=="/n") i++;
    strcat(a[i][j],a[i][j]);
    strcat(a[i][j],c);
    }while (feof(fp)==0);
     
    fclose(fp);
     
    return 0;
    }
    Fichiers attachés Fichiers attachés

  2. #2
    Membre Expert Avatar de fregolo52
    Homme Profil pro
    Développeur C
    Inscrit en
    Août 2004
    Messages
    2 366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Août 2004
    Messages : 2 366
    Par défaut
    y'a un souci dès le début :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char *a[65000][256];
    for(i=1;i<=65000;i++) {for(j=1;j<=256;j++)*a[i][j]=0;};
    c'est i=0;i< sinon tu vas taper en dehors de ton tableau.

    Ton autre problème c'est que tu crées un tableau de pointeur sans allocation mémoire.

    Plus simplement, que cherches-tu à faire avec ce code ? (qu'y a-t-il dans tt.txt)

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 18
    Par défaut
    Bonjour Fregolo,

    Merci de répondre.

    Le fichier est de type export texte excel.

    Il s'agit d'une lecture sur un mobile comme les tableurs sont pas térribles

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 18
    Par défaut
    (ce qui est de l'allocation évidemment je m'en suis rendu compte cependant je n'y arrive pas sans déclencher des erreurs de conversion de type)

    Le code proposé est celui qui ne provoque pas d'erreur de compilation.

  5. #5
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Salut.

    Citation Envoyé par Aurel5477 Voir le message
    Le code proposé est celui qui ne provoque pas d'erreur de compilation.
    Oui, c'est syntaxiquement correct.
    M'enfin bon...

    Citation Envoyé par Aurel5477 Voir le message
    (ce qui est de l'allocation évidemment je m'en suis rendu compte cependant je n'y arrive pas sans déclencher des erreurs de conversion de type)
    Pourtant il n'y a rien de compliqué.
    Si T est le type des données pour lesquelles tu veux allouer de la mémoire et n le nombre d'éléments que tu veux crééer, les expressions génériques suivantes permettent d'allouer correctement la mémoire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    T *p = (T *) malloc(n * sizeof(T));
    T *q = (T *) calloc(n, sizeof(T));
    La différence entre les deux, c'est que pour la première, on se contente de réserver l'espace mémoire nécessaire, alors que pour la seconde on initialise cette zone avec des 0.

  6. #6
    Membre Expert Avatar de fregolo52
    Homme Profil pro
    Développeur C
    Inscrit en
    Août 2004
    Messages
    2 366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Août 2004
    Messages : 2 366
    Par défaut
    La question qu'il faut se poser est : est ce que la déclaration est correcte
    Représente 3 dimensions

    Si tu cherches à stoker 65000 ligne de 256 caractères (max), la bonne déclaration est :
    Et ca va simplifier énormément les choses

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

    Informations forums :
    Inscription : Octobre 2011
    Messages : 18
    Par défaut
    ça n'a effectivement pas l'air compliqué, mais j'ai toujours une conversion invalide char* à char quand je mets la forme 1 dans ma boucle de la ligne 16

  8. #8
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Maintenant concernant ton code...

    Tout d'abord, la première chose qui me frappe, c'est que tu écris du code C, mais tu postes sur le forum C++.
    Ce serait bien de résoudre cette petite incohérence...
    Bon, pour la suite, je vais supposer que tu veux faire du C, et que tu t'es trompé de forum (ou que tu as voulu ratisser large).


    Ensuite, comme l'a souligné fregolo52, tu utilises des pointeurs sans allocation.
    Que ce soient c, c2, c3, ou les 65000*256 éléments de a, ce sont des pointeurs qui ne pointent pas sur une zone dédiée (réservée).
    Ça peut être voulu, mais ce n'est pas le cas ici.

    Le premier paramètre de la fonction fgets indique à quelle adresse écrire les données lues depuis le flux.
    La zone mémoire pointée doit avoir été allouée (réservée), et être suffisamment grande pour recevoir toutes les données (d'où l'utilité du deuxième paramètre).
    Or, non seulement tu n'as pas alloué de mémoire (statiquement ou dynamiquement) pour stocker ces données, mais en plus la valeur du pointeur que tu passes en paramètre est NULL !
    Autrement dit, aux lignes 25 et 27, tu essaies d'écrire à l'adresse 0x0, ce qui n'est évidemment pas une adresse valide.
    Pas étonnant que tu obtiennes une erreur de segmentation...


    Quand on y regarde de plus près, à ces mêmes lignes, tu ne lis qu'un seul caractère à la fois.
    Dans ce cas, tu n'as peut-être pas besoin d'utiliser un pointeur sur un caractère, mais directement un caractère, et passer l'adresse de ce caractère à la fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char c;
    (...)
    fgets(&c, 1, fp),
    Cela résoudrait le problème d'allocation mémoire...

    Et puisque tu lis caractère par caractère, tu aurais peut-être également intérêt à utiliser fgetc à la place de fgets.
    Il faut juste se souvenir que fgetc retourne la constante EOF une fois arrivée à la fin du flux.
    Mais bon, c'est à toi de voir ce qui est le plus simple pour toi.


    Je crois que les tests des lignes 32 et 33 ne font pas ce que tu attends.
    L'expression (c == "/t") signifie :
    Tester si l'adresse pointée par c est la même que l'adresse de la chaîne de caractères (constante) "/t"
    ce qui est différent de :
    Tester si la chaîne de caractères pointée par c est égale à la chaîne de caractères "/t"
    Si tu veux tester l'égalité entre deux chaînes de caractères, tu es obligé d'utiliser la fonction strcmp.


    Pour les lignes 34 et 35, c'est exactement le même problème que pour les lignes 25 et 27.
    Le premier paramètre de strcat doit pointer sur une zone mémoire (allouée) suffisamment grande pour contenir tous les caractères de la chaîne de caractère qui résultera de l'opération.
    Autrement dit, pour l'expression strcat(dest, src), la taille de la zone mémoire pointée par dest doit être supérieure ou égale à strlen(dest) + strlen(src) + 1 (ne pas oublier le caractère NUL à la fin de la chaîne).


    Sinon, quelques remarques en vrac :
    • Tu as vraiment besoin de c3 ? Tu ne l'utilises pas dans ton code...
    • Quand on ouvre un flux, on vérifie qu'il a bien été ouvert avant de l'utiliser (si ce n'est pas le cas, fopen retourne NULL).
    • Pourquoi tu ouvres ton flux avec le mode "a+" vu que tu n'écris jamais dedans ? "r" serait suffisant.
    • [Edit]De plus, en te contentant d'ouvrir le flux en lecture seule, tu n'as pas besoin d'appeler rewind pour replacer le curseur au début du flux.[/Edit]
    • Pourquoi tu reviens en arrière après tes lectures ? Vu comment c'est fait, le premier caractère lu d'une itération sera le même que le dernier caractère lu de l'itération précédente...
    • Vu que tu reviens en arrière avant de tester si tu es à la fin du fichier, tu ne risques pas de l'atteindre... Par contre, tu peux y arriver au milieu de ta boucle, et je ne sais pas trop ce qu'il se passe quand tu essaies de te déplacer dans ton flux par rapport à la position courante alors que tu as déjà atteint la fin du flux...

  9. #9
    Membre Expert Avatar de fregolo52
    Homme Profil pro
    Développeur C
    Inscrit en
    Août 2004
    Messages
    2 366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Août 2004
    Messages : 2 366
    Par défaut
    je réitaire ma question :

    Que cherches-tu à faire avec ce code ? "Il s'agit d'une lecture sur un mobile comme les tableurs sont pas térribles " ca ne nous dit rien sur ton algo de recherche dans le fichier.

    Quand je lis le code :
    - déclaration d'un pointeur sur un tableau à 2 dimension
    - initialisation du tableau à 2 dimension. le pointeur n'est pas initialisé => segmentation fault.

    la boucle while est affreuse avec les fgets et fseek.
    cette ligne strcat(a[i][j],a[i][j]); est des plus étrange.

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

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Par défaut
    c'est toujours écrit comme ça?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for(i=1;i<=65000;i++) {for(j=1;j<=256;j++)*a[i][j]=0;};
    Parce que c'est un soucis...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    char a[65000][256];
     
    for(i=1;i<=65000;i++) {
        for(j=1;j<=256;j++){
           a[i][j]=0;
        }
    };
    (j'ai rajouté les alinées et accolades pour la lecture, c'est le fait d'enlever l'étoile qui compte)

  11. #11
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Citation Envoyé par Aurel5477 Voir le message
    j'ai toujours une conversion invalide char* à char quand je mets la forme 1 dans ma boucle de la ligne 16
    Je n'avais pas vu qu'il y a aussi une erreur à cette ligne.

    Tu déclares ton tableau de la manière suivante : char *a[65000][256];.
    Donc, si i et j sont des entiers :
    • a est du type char *** ;
    • a[i] est du type char ** ;
    • a[i][j] est du type char * ;
    • *a[i][j] est du type char.
    (en simplifiant...)

    À la ligne 16, tu essaies d'affecter un char * (le résultat de l'allocation de mémoire) à un char (*a[i][j]).
    Pas étonnant que tu aies une erreur de conversion de type !
    De plus, tu essaies de déréférencer un pointeur qui n'a pas été initialisé.
    Très dangereux...

  12. #12
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    @therwald Ce serait peut-être mieux comme ça, non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    char a[65000][256];
     
    for(i=0;i<65000;i++) {
        for(j=0;j<256;j++){
           a[i][j]=0;
        }
    };

    Mais il veut peut-être réellement utiliser un tableau de pointeurs à deux dimensions...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    char *a[65000][256];
     
    for(i=0;i<65000;i++) {
        for(j=0;j<256;j++){
           a[i][j]=0;
        }
    };

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

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Par défaut
    Citation Envoyé par Steph_ng8 Voir le message
    @therwald Ce serait peut-être mieux comme ça, non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    char a[65000][256];
     
    for(i=0;i<65000;i++) {
        for(j=0;j<256;j++){
           a[i][j]=0;
        }
    };
    Exact, j'avais oublié la correction des bornes

  14. #14
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Citation Envoyé par fregolo52 Voir le message
    La question qu'il faut se poser est : est ce que la déclaration est correcte
    Représente 3 dimensions

    Si tu cherches à stoker 65000 ligne de 256 caractères (max), la bonne déclaration est :
    Et ca va simplifier énormément les choses
    Oh, je n'avais pas vu ce message.
    Il faut juste préciser qu'il ne faut pas oublier le caractère NUL de fin de chaîne, et donc que chaque chaîne du tableau ne pourra contenir au maximum que 255 caractères non-nuls.

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

    Informations forums :
    Inscription : Octobre 2011
    Messages : 18
    Par défaut
    Analyse assez complète Steph. Je vais prendre ça point par point merci.
    Fregolo: le but est juste de travailler sur un tableau texte ligne-colonne.

  16. #16
    Membre Expert Avatar de fregolo52
    Homme Profil pro
    Développeur C
    Inscrit en
    Août 2004
    Messages
    2 366
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Août 2004
    Messages : 2 366
    Par défaut
    Citation Envoyé par Aurel5477 Voir le message
    Analyse assez complète Steph. Je vais prendre ça point par point merci.
    Fregolo: le but est juste de travailler sur un tableau texte ligne-colonne.
    Vu que tu n'as pas l'air de vouloir nous dire quelle est ta logique de travail (stockage dans le tableau):
    Peux-tu nous dire ce que tu veux faire avec ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (c=="/t") j++;
    if (c=="/" && c2=="/n") i++;
    strcat(a[i][j],a[i][j]);
    strcat(a[i][j],c);

  17. #17
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Si tu pouvais également ajouter un exemple de fichier à lire, ça serait pas mal...

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

    Informations forums :
    Inscription : Octobre 2011
    Messages : 18
    Par défaut
    Oui bien sûr,pour la logique de l'algo c'est :
    je lis mon fichier caractère par caractère
    je reconstitue la chaine tant qu'elle est continue en la plaçant dans mon tableau
    si je rencontre un espace je change de colonne j
    si je rencontre un retour à la ligne je change de ligne i

    Merci de prendre du temps pour ce problème bébête.

  19. #19
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 18
    Par défaut
    L'indexation n'est pas bonne de toute façon il me faut i,j k,l par exemple.

    Je suis aller trop vite avec mes morceau de ligne de code

  20. #20
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2011
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2011
    Messages : 18
    Par défaut
    Avec 2 tableaux bien sûr.

Discussions similaires

  1. Réponses: 5
    Dernier message: 23/12/2009, 11h31
  2. Réponses: 5
    Dernier message: 09/06/2009, 10h30
  3. Problème : pas de segmentation fault ?!
    Par Loïc B. dans le forum C++
    Réponses: 3
    Dernier message: 05/11/2007, 17h08
  4. Réponses: 13
    Dernier message: 13/07/2004, 15h41
  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