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 :

Modification de pointeurs dans une fonction


Sujet :

C

  1. #1
    Membre habitué Avatar de bluemartini
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    154
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Avril 2006
    Messages : 154
    Points : 168
    Points
    168
    Par défaut Modification de pointeurs dans une fonction
    Après 2 ans d'inactivité en langage C, je me relance dedans. Et avec des pointeurs, même pas peur.
    Sauf que je n'y arrive pas, et il me semble à cause d'une erreur de débutant...

    Voilà, j'ai un fichier tabulé à parser qui ressemble à ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Hs:NCBIv35:chr1    1703    13.07712
    Hs:NCBIv35:chr1    1736    14.447635
    Hs:NCBIv35:chr1    1769    14.679797
    Hs:NCBIv35:chr1    1799    14.679797
    j'ai une fonction file2matrice qui doit me permettre de placer dans 3 vecteurs les 2 dernières colonnes ainsi que le dernier chiffre de la première colonne, et qui me rend le nombre de lignes lues :

    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
     
    int file2matrice(FILE * fichier, int * chr, int * pos, double * val){
        int nb_lignes_lues = 0;//nombre de lignes lues
        int i;//variable bidon
        char ligne [LG_MAX];//longueur max lue dans un fichier
        char ** contenu;//contenu de la ligne splittée par tabulation
     
     
        while(fgets(ligne, LG_MAX, fichier) != NULL) {
     
            //on récupère le contenu de ligne
            contenu = str_split(ligne,"\t");//fonction pour splitter une ligne
     
            //on alloue de la mémoire supplémentaire
            pos = realloc(pos, (nb_lignes_lues+1)*sizeof(int));
            val = realloc(val, (nb_lignes_lues+1)*sizeof(double));
     
            *(val+nb_lignes_lues) = atof(*(contenu+2));
            *(pos+nb_lignes_lues) = atoi(*(contenu+1));
     
            nb_lignes_lues++;
        }//while
     
        //verification
        for(i=0;i<nb_lignes_lues;i++){
            printf("%f\t",*(val+i));
            printf("%d\n",*(pos+i));
        }
     
        return nb_lignes_lues;
    }
    pour l'instant je ne charge que les deux dernières colonnes. la dernière boucle étant là pour vérifier les données contenues dans les deux vecteurs concernés.
    Jusqu'ici tout va bien, j'ai bien les bonnes données enregistrées. Mais dans le main, je lance la fonction :


    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
     
    int main(int argc , char *argv[]){
        FILE * f;
        int * chrom = (int*) malloc(1*sizeof(int));
        int * position = (int*) malloc(1*sizeof(int));
        double * pvalue = (double*) malloc(1*sizeof(double));
        int i; //variable bidon
        int taille = 0;//nombre de lignes enregistrées
     
        //importation du fichier
        f = fopen("/home/data/test2.txt","r");
        if(f==NULL){
            perror("fichier 1\n");
        }
        taille = file2matrice(f, chrom, position, pvalue);
        fclose(f);
        printf("%d lignes lues\n",taille);
     
        for(i=0;i<taille;i++){
            printf("%f\t",*(pvalue+i));
            printf("%d\n",*(position+i));
        }
     
        return 0;
    }
    j'ai en réponse avec la dernière boucle soit 0 soit des valeurs fantaisistes. Alors à quel moment mon pointeur perd son adresse?


    Merci pour vos réponses

  2. #2
    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
    Il faut se rappeler qu'un paramètre d'une fonction définit une variable locale initialisée par l'argument utilisé lors de l'appel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int file2matrice(FILE * fichier, int * chr, int * pos, double * val){
    ....
            //on alloue de la mémoire supplémentaire
            pos = realloc(pos, (nb_lignes_lues+1)*sizeof(int));
            val = realloc(val, (nb_lignes_lues+1)*sizeof(double));
    Or realloc peut modifier les adresses pos et val ! En conséquence, ces reallocations modifient les variables locales pos et val, mais pas du tout les variables utilisées lors de l'appel dans main().

    Si c'est le cas, le code dans main
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        for(i=0;i<taille;i++){
            printf("%f\t",*(pvalue+i));
            printf("%d\n",*(position+i));
    accède à des zones désallouées. Si tu as de la chance, le programme plante à cet endroit. Si tu n'en as pas, le programme marche de temps en temps, donne de temps en temps des résultats baroques et plante les autres fois.
    Si une fonction fait un realloc d'une zone allouée ailleurs, il faut qu'elle puisse modifier les adresses utilisées lors de l'appel.

    Accessoirement,
    - supprime le cast devant malloc dans main. Il est inutile et considéré comme néfaste. (d'ailleurs tu n'as pas éprouvé le besoin de l'utiliser devant realloc).
    - La notation *(a+b) est avantageusement remplaçable par a[b] (ou b[a])
    - A quoi sert le paramètre chr dans la fonction int file2matrice(FILE * fichier, int * chr, int * pos, double * val)
    - atoi et atof sont obsolètes. Utiliser plutôt strtol et strtod
    Publication : Concepts en C

    Mon avatar : Glenn Gould

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

  3. #3
    Membre habitué Avatar de bluemartini
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    154
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Avril 2006
    Messages : 154
    Points : 168
    Points
    168
    Par défaut
    Merci beaucoup pour ta réponse diogene.
    Effectivement c'était une erreur de débutant...

    Tu m'as bien aidé, et les conseils supplémentaires sont enregistrés!
    Encore merci, bonne soirée!

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Et aussi, ton utilisation de realloc() est imprudente, car elle cause une fuite de mémoire en cas d'échec.
    http://emmanuel-delahaye.developpez....es.htm#realloc

    De plus, pour des raisons de performance, tu devrais réallouer de manière géométrique (exemple: Multiplier la taille par 1.5) plutôt que d'ajouter 1 à chaque fois: Cela te permettra d'appeler realloc() moins souvent...
    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.

  5. #5
    Membre habitué Avatar de bluemartini
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    154
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Avril 2006
    Messages : 154
    Points : 168
    Points
    168
    Par défaut
    Merci de ces précisions Médinoc

    Effectivement, la ré-allocation à chaque boucle était une mauvaise idée, je comptais changer cela (à coups de 100,000 lignes en fait) après avoir résolu le problème de perte de pointeur.
    Pour le realloc dangereux, je me suis permis de pêcher par excès d'optimisme, car c'est le seul programme à tourner pour l'instant sur une machine généreuse en mémoire! Mais c'est juste que c'est assez imprudent.

    Merci encore

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

Discussions similaires

  1. passage de pointeur dans une fonction
    Par El Manco dans le forum Débuter
    Réponses: 10
    Dernier message: 09/02/2009, 22h13
  2. Modifier le contenu de pointeurs dans une fonction
    Par Sol_Invictus dans le forum Débuter
    Réponses: 6
    Dernier message: 11/09/2008, 23h30
  3. Pointeur dans une fonction ?
    Par sliiim6184 dans le forum C
    Réponses: 4
    Dernier message: 28/12/2006, 11h32
  4. Modification de onSubmit dans une fonction javascript
    Par kalan dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 23/11/2006, 14h13
  5. [Turbo Pascal] Allocation et désallocation de pointeurs dans une fonction
    Par neird dans le forum Turbo Pascal
    Réponses: 13
    Dernier message: 17/11/2002, 20h14

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