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 :

Problème allocation dynamique de char* en c


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti Avatar de ethan007
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2015
    Messages : 20
    Par défaut Problème allocation dynamique de char* en c
    Bonsoir à tous, je fais un projet et je viens de rencontrer un petit disfonctionnement je cherche des explications...
    J'ai un fichier qui contient la définiton d'une matrice (en première ligne du fichier on a le nombre de ligne et le nombre de colonne (de la matrice), puis la suite c'est la matrice elle même)
    EX:
    3 3
    1 2 3
    4 5 6
    7 8 9

    Mon but est d'écrire une fonction qui lit le contenu du fichier et renvoie tous ce contenu (y compris la première ligne) sous forme de char* et voici mon code (qui fonctionne..fin je pense):
    gestion_fichiers.c
    Code c : 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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "gestion_fichiers.h"
     
    char *lire_fichier(char *nom_fichier){
        FILE *fichier = fopen(nom_fichier, "r");
        int nbreL = fgetc(fichier);
        nbreL = (int)nbreL - '0';//cast
        fgetc(fichier); //Espace entre le nombre de lignes et le nombre de colonnes au début du fichier
        int nbreC = fgetc(fichier);
        nbreC = (int)nbreC - '0';//cast
     
        int taille_ligne = nbreC + (nbreC -1);//La taille de la ligne à lire se calcule en incluant les espaces, pour n colonnes il y a n-1 espaces
        char *current_line_data = (char*)malloc(nbreC * sizeof(char));
        char *file_data = (char*)malloc(nbreC * nbreL * sizeof(char)+3); //will store the retrieved data # +3 is the nbreL space and nbreC
        printf("L = %d et C = %d", nbreL, nbreC);
        fseek(fichier, 0, SEEK_SET);//Get the cursor back to first ligne
        strcat(file_data, fgets(current_line_data, 4, fichier));//La première ligne du fichier
     
        if(fichier != NULL){
            while(fgets(current_line_data, taille_ligne +1, fichier)){
     
                strcat(file_data, current_line_data);//We are sure the space is enough for all datas because we calculated it earlier
            }
        }else{
            printf("The file %s doest not exist! exiting...", nom_fichier);
            exit(1);//Error can be handleled
        }
     
        free(current_line_data);
        return file_data;
    }
     
    void desallouer_donnees_fichier(char *ptr_datas){
        free(ptr_datas);
    }
    le .h:
    gestion_fichiers.h
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    #include <stdio.h>
    #include <stdlib.h>
    char *lire_fichier(char *nom_fichier);
    void desallouer_donnees_fichier(char *ptr_datas);
    Dans le main j'appelle ma fonction avec le code suivant:
    main.c:
    Code c : 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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include "gestion_fichiers.h"
     
    int main(){
     
     
    printf("\n-----------GESTION DU FICHIER!-------\n");
    	char *donnees = lire_fichier("file.txt");
    	printf("Affichage des données:\n %s", donnees);
    	printf("\n-----------AUREVOIR !-------\n");
     
    	//desallouer_matrice(mat);
    	//desallouer_matrice(produit);
    	desallouer_donnees_fichier(donnees);
    	return 0;
    }

    Ce code marche bien mais lorsque je déboguait ailleurs j'ai constaté que la ligne 16 du fichier "gestion_fichiers.c" n'alloue pas un tableau de char de taille nbreC * sizeof(char)
    En réalité j'a remplacé cette ligne par:
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char *current_line_data = (char*)malloc(1);
    qui normalement devrait allouer 1 octet, ce qui devait me faire apparaitre une belle érreur de ségmentation (mon ami de tous les jours :p) à la ligne 24 mais au contraire tous ce passe bien : je me demande donc est ce que le fait que j'ai utilisé un malloc ou fgets le pousse recalculer la nouvelle taille à chaque tour de la boucle qui est à la lgine 24???

    Best regards.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 152
    Billets dans le blog
    4
    Par défaut
    Donc tu veux juste lire un fichier et stocker son contenu dans un char* ?
    fopen
    fseek
    ftell
    rewind
    fread
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre averti Avatar de ethan007
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2015
    Messages : 20
    Par défaut
    Bonsoir merci pour cette réponse rapide, en fait j'ai oublié de dire que c'est un projet d'école et les contraintes c'est d'utiliser uniquement fgets pour renvoyer le char*.
    or fgets en boucle écrase à chaque itération.

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

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

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

    Ligne 16, tu n'alloues pas assez de caractères, il faut aussi réserver de la place pour le terminateur et le caractère de retour chariot.
    Ligne 17, je n'ai refait le calcul. Mais j'ai de gros doutes sur le nombre réservé.
    Ligne 20, tu concatènes dans file_data, donc tu supposes qu'initialement elle est vide, mais où est-ce fait? Et pire qu'y a-t-il dans current_line_data? On n'y a jamais rien mis.

    Maintenant pourquoi 1 semble suffire ligne 16? Si on n'alloue pas pas assez de place on a un "undefined behavior", ce qui veut dire que tout est possible et en particulier cela peut sembler fonctionner. Les caractères en trop se retrouvent dans un endroit non réservé, non prévu qui peut casser une autre partie du logiciel. Pour certains compilateurs quand on demande 1 octet on en obtient parfois 7 de plus en "cadeau", c'est ce qui doit ce passer dans ton cas.

  5. #5
    Membre averti Avatar de ethan007
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2015
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2015
    Messages : 20
    Par défaut
    Bonsoir
    Citation Envoyé par dalfab Voir le message
    Bonjour,

    Ligne 16, tu n'alloues pas assez de caractères, il faut aussi réserver de la place pour le terminateur et le caractère de retour chariot.
    Exact, merci
    Citation Envoyé par dalfab Voir le message
    Ligne 17, je n'ai refait le calcul. Mais j'ai de gros doutes sur le nombre réservé.
    En effet j'aurai dû penser aux espaces
    Citation Envoyé par dalfab Voir le message
    Ligne 20, tu concatènes dans file_data, donc tu supposes qu'initialement elle est vide, mais où est-ce fait?
    Bon je devrait lui affecter NULL avant de faire le malloc?
    Citation Envoyé par dalfab Voir le message
    Et pire qu'y a-t-il dans current_line_data? On n'y a jamais rien mis.
    current_line_data est rechargé à chaque tour de boucle while(gets..) de la ligne 23
    Citation Envoyé par dalfab Voir le message
    Maintenant pourquoi 1 semble suffire ligne 16? Si on n'alloue pas pas assez de place on a un "undefined behavior", ce qui veut dire que tout est possible et en particulier cela peut sembler fonctionner. Les caractères en trop se retrouvent dans un endroit non réservé, non prévu qui peut casser une autre partie du logiciel. Pour certains compilateurs quand on demande 1 octet on en obtient parfois 7 de plus en "cadeau", c'est ce qui doit ce passer dans ton cas.
    Ah soulagement je cherchait une explication là dessus, c'est donc peu être le fameux "undefined behavior" qui a de la chance d'aller dans des blocs inutilisés..
    [/QUOTE]
    Citation Envoyé par dalfab Voir le message
    Pour certains compilateurs quand on demande 1 octet on en obtient parfois 7 de plus en "cadeau", c'est ce qui doit ce passer dans ton cas
    mais pourquoi est ce que le compilateur devrait allouer ne serait-ce que 1 octet de plus alors que j'en ai demandé un nombre exact? imaginons un programmeur sur un carte avec quelques Ko..

  6. #6
    Expert confirmé
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 226
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 226
    Par défaut
    Citation Envoyé par ethan007 Voir le message
    mais pourquoi est ce que le compilateur devrait allouer ne serait-ce que 1 octet de plus alors que j'en ai demandé un nombre exact? imaginons un programmeur sur un carte avec quelques Ko..
    Cela n'est pas à cause de ton compilateur mais de ton processeur et c'est ce qu'on appelle l'alignement.

    Sur une machine de quelque ko , les contraintes ne sont pas les mèmes et donc un processeur 8 bits n'a aucune mal a gérer la mémoire si elle n'est pas aligné.
    (Mais si tu as vraiment besoin d'économiser la mémoire jusqu'a ce que la pile te pose souci , alors tu peux aller en assembleur).

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

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

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Citation Envoyé par ethan007 Voir le message
    Bon je devrait lui affecter NULL avant de faire le malloc?
    Avant malloc!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    // que fait ce code ?
    char *current_line_data = "hello";
    current_line_data = NULL;
    current_line_data = malloc(nbreC +2);
    // ou, même question, que fait ce code ?
    double a = 3.14159;
    a = 0;
    a = 5 * 3;
    Après malloc, on peut initialiser le 1er caractère à '\0' ou commencer par strcpy() plutôt qur strcat().
    Citation Envoyé par ethan007 Voir le message
    current_line_data est rechargé à chaque tour de boucle while(gets..) de la ligne 23
    Et par quelle magie, en ligne 20 c'est déjà rempli?
    Citation Envoyé par ethan007 Voir le message
    mais pourquoi est ce que le compilateur devrait allouer ne serait-ce que 1 octet de plus alors que j'en ai demandé un nombre exact? imaginons un programmeur sur un carte avec quelques Ko..
    J'ajoute aux réponses précédentes que sur les cartes avec quelques Ko (c'est mon métier) on n'alloue jamais rien saufs de rares grands blocs (c-a-d quelques centaines d'octets), la perte relative est donc négligeable.

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

Discussions similaires

  1. problème allocation dynamique dans C++
    Par mido1951 dans le forum C++
    Réponses: 16
    Dernier message: 23/04/2013, 21h38
  2. problème allocation dynamique tableau 2d
    Par virtual_bug dans le forum C++
    Réponses: 16
    Dernier message: 17/04/2012, 11h21
  3. Réponses: 4
    Dernier message: 06/05/2008, 13h12
  4. Problème allocation dynamique ?
    Par Dark_Alex69 dans le forum C
    Réponses: 15
    Dernier message: 20/11/2007, 15h44
  5. problème allocation dynamique
    Par josef24 dans le forum Débuter
    Réponses: 6
    Dernier message: 12/11/2007, 12h31

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