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 :

grr.. encore un pb d'alloc :s (realloc & strncat)


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé

    Inscrit en
    Janvier 2006
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 188
    Par défaut grr.. encore un pb d'alloc :s (realloc & strncat)
    Voici une fonction qui doit mettre en mémoire un fichier texte dans un char * :
    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
     
    #define fichierConf "config.php"
    int main(int argc, char *argv[], char **envp){
        char *confSrc="yep";    
        loadTextFile(fichierConf, &confSrc);
        printf("%s",confSrc);
        free(confSrc);    
        exit(0);
    }
     
     
    void loadTextFile(char *name, char **stockage){
        #define tailleBuffer 512
        char buffer[tailleBuffer];
        FILE *file;
        int NbLu;
        int taille=strlen(*stockage);
        printf("TAille initiale : %i\n",taille);
     
        if((file=fopen(name, "r")) == NULL){
    	printf("Ouverture impossible du fichier %s :s\n",name);	
    	exit(1);
        }
     
        while( (NbLu=fread(buffer, 1, tailleBuffer, file)) != 0){
    	taille+=NbLu;
    	*stockage=(char *) realloc(*stockage,taille+1);
    	strncat(*stockage,buffer,NbLu);
    	(*stockage)[taille-1]=0x0;
        }
        fclose(file);
    }
    Quand mon char * de stockage (confSrc) est initialisé à 0x0, le prog marche mais j'ai un caractère bizarre qui s'insère au tout début. Par contre, quand il est déjà initialisé, le prog plante

  2. #2
    Futur Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2006
    Messages
    3
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3
    Par défaut
    Salut ramislebob,
    Je pense que ton problème vient plus de l'utilisation hasardeuse de la chaîne "yep" affectées directement au char * confSrc, que d'une défaillance des fonctions d'allocations (bien que je te déconseille de continuer avec realloc).
    Mon prof d'algo-prog m'a un jour expliqué que les chaînes litérales "..." étaient stockées quelque part en mémoire dans un endroit qu'il ne vaut mieux pas manipuler.
    Je te conseille d'essayer l'affectation suivante :
    char *confSrc = (char *) malloc(4);
    strcpy(confSrc, "yep");
    confSrc[4] = 0x0;
    .
    Je crois que ton affaire ne s'en portera pas plus mal...

  3. #3
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    On ne peut re-allouer qu'un pointeur NULL ou associe a un espace memoire retourne par malloc(). Rien d'autre. Et ton code est tres moche...

    En general, on re-alloue en doublant la taille allouee (car c'est une fonction potentiellement couteuse). Il faut donc maintenir un compteur du nombre de caracteres lus, a comparer avec l'espace memoire disponible. Egalement, puisque tu lis un fichier texte, fgets() est plus appropriee que fread().

  4. #4
    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
    Si j'ai bien compris une discussion précédente, il est déconseillé de multiplier la taille alloué par un nombre supérieur au nombre d'or (2 > 1.62), la raison s'expliquant par une suite de Fibonacci...

    Compte tenu de ce critère, il est courant qu'on multiplie la taille par 1.5 (mais on pourrais aussi la multiplier par la racine de deux si l'on voulait)...
    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 Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Citation Envoyé par Médinoc
    Si j'ai bien compris une discussion précédente, il est déconseillé de multiplier la taille alloué par un nombre supérieur au nombre d'or (2 > 1.62), la raison s'expliquant par une suite de Fibonacci...
    Encore des mathematiciens desoeuvres

    J'avais aussi oublie d'ecrire que realloc() ne s'utilise pas comme cela. En effet, si elle echoue en renvoyant NULL, l'espace alloue precedemment n'est pas libere. Si on ecrase la valeur du pointeur par NULL, alors cet espace est perdu (fuite memoire).
    Il faut utiliser un pointeur temporaire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    type *ptr = realloc(old_ptr, new_size);
    if (ptr != NULL)
    {
      old_ptr = ptr;
      ...
    }
    else
    {
       free(old_ptr);
       /* error */
    }
    Evidemment, au lieu de faire le free(old_ptr), on peut mettre en place un mecanisme plus sophistique (reclamer de la memoire non utilisee et retenter le realloc() par exemple).

  6. #6
    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <stdlib.h>
     
    int MyRealloc(void ** ppData, size_t newSize)
    {
    	void *pTmp = realloc(*ppData, newSize);
    	if(pTmp == NULL)
    		return -1;
    	else
    	{
    		*ppData = pTmp;
    		return 0;
    	}
    }
    Et ça s'appelle ainsi (là hélas, je crois bien que le cast est obligatoire)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if( MyRealloc((void**) &buf, new_size) )
    {
    	/* erreur */
    }
    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.

  7. #7
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    Code bien compliqué qui implique des erreurs...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    loadTextFile(fichierConf, &confSrc);
    
    void loadTextFile(char *name, char **stockage)// Quel est l'intérêt?
    {
    ...
    }
    Je ferais ainsi:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    loadTextFile(fichierConf, confSrc);
     
    void loadTextFile(char *name, char *stockage)
    {
    ...
    }
    Pour l'allocation dynamique:
    Je te conseille d'essayer l'affectation suivante :
    Citation:
    char *confSrc = (char *) malloc(4);
    Plutot cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    #define NbCaract 4
     
    char *confSrc = malloc(NbCaract * sizeof(*confSrc));
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *stockage=(char *) realloc(*stockage,taille+1);
    Stocker l'adresse sur laquelle il faut pointer dans le contenu de l'adresse pointée par stockage, c'est pas logique....

  8. #8
    Membre confirmé

    Inscrit en
    Janvier 2006
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 188
    Par défaut
    Citation Envoyé par prof Tournesol
    Je pense que ton problème vient plus de l'utilisation hasardeuse de la chaîne "yep" affectées directement au char * confSrc, que d'une défaillance des fonctions d'allocations (bien que je te déconseille de continuer avec realloc).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    char *confSrc = (char *) malloc(4);
    strcpy(confSrc, "yep");
    confSrc[4] = 0x0;
    Effectivement, bien vu
    ça résout le pb ^^

    Citation Envoyé par DaZumba
    On ne peut re-allouer qu'un pointeur NULL ou associe a un espace memoire retourne par malloc(). Rien d'autre. Et ton code est tres moche...
    Quand j'initialise mon char* à NULL, plantage :s
    en revanche un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        char *confSrc = (char *) malloc(1);
        confSrc[0]=0x0;
    permet une initialisation à vide.
    bref, realloc semble ne s'appliquer QUE à un espace mémoire alloué par malloc.

    Citation Envoyé par DaZumba
    Et ton code est tres moche...
    pourkoi :s ? je vois pas trop comment faire autrement, plus propre...
    j'attends des suggestions

    Citation Envoyé par DaZumba
    puisque tu lis un fichier texte, fgets() est plus appropriee que fread().
    je vais regarder la doc de fgets, y a longtemps que je l'ai pas utilisé.


    Citation Envoyé par homeostasie
    loadTextFile(fichierConf, confSrc);

    void loadTextFile(char *name, char *stockage)
    {
    ...
    }
    ben il me semble que ça ne va pas. Pour modifier un char * dans une fonction il faut lui passer en param un pointeur sur ce char *... dites me si je me trompe mais je ne pense pas.


    Citation Envoyé par homeostasie
    *stockage=(char *) realloc(*stockage,taille+1);

    Stocker l'adresse sur laquelle il faut pointer dans le contenu de l'adresse pointée par stockage, c'est pas logique....
    Pas compris ce que tu veux dire. *stockage est un char *, l'adresse du début de mon string. stockage est un pointeur sur mon string.


    Citation Envoyé par DaZumba
    J'avais aussi oublie d'ecrire que realloc() ne s'utilise pas comme cela. En effet, si elle echoue en renvoyant NULL, l'espace alloue precedemment n'est pas libere. Si on ecrase la valeur du pointeur par NULL, alors cet espace est perdu (fuite memoire).
    Merci de m'avoir rajouter la remarque, cé vrai que j'avais totalement zappé ce point plutot important.. :s

    Citation Envoyé par DaZumba
    on peut mettre en place un mecanisme plus sophistique (reclamer de la memoire non utilisee et retenter le realloc() par exemple).
    qu'est ce que tu entends par "réclamer de la mémoire" ? est il possible de connaitre la mem disponnible ?


    Citation Envoyé par Médinoc
    Et ça s'appelle ainsi (là hélas, je crois bien que le cast est obligatoire)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    if( MyRealloc((void**) &buf, new_size) )
    {
    	/* erreur */
    }
    cé koi un cast ?
    le transtipage en (void **) est il vraiment nécessaire ? ça compile très bien sans.
    Rq : j'ai récup ta fonction, merci.

    Bon.. voilà mes remarques / questions :p
    encore merci à tous

  9. #9
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Citation Envoyé par ramislebob
    bref, realloc semble ne s'appliquer QUE à un espace mémoire alloué par malloc.
    D'apres la norme du langage C, un appel realloc(NULL, size) est equivalent a malloc(size) et un appel realloc(ptr, 0) est equivalent a free(ptr).
    De plus, c'est quoi 0x0 ? Autant utiliser NULL ou 0, au moins on est sur que le compilateur mettre bien le pointeur a l'adresse invalide correspondant a NULL, qui n'est pas forcement 0x0.

    Citation Envoyé par ramislebob
    pourkoi :s ? je vois pas trop comment faire autrement, plus propre...
    j'attends des suggestions
    D'abord, la programmation C n'est pas un concours de compression de donnees. Une ligne comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if((file=fopen(name, "r")) == NULL){
    est plus agreablement ecrite ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    file = fopen(name, "r");
    if (file == NULL)
    {
      ...
    }
    Non ?
    Ensuite, je te conseille d'ecrire les erreurs sur stderr (qui peut etre redirige independamment de stdout, ce qui est pratique).
    Donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    printf("Ouverture impossible du fichier %s.\n",name);
    devient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    fprintf(stderr, "Ouverture impossible du fichier %s.\n",name);
    Le exit(1) en cas d'echec est trop violent. Il faut remonter un code d'erreur a main(), qui est la seule fonction terminant le programme. Le prototype de ta fonction devient alors
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int loadTextFile(char *name, char **stockage)
    et main() teste le retour de cette fonction (et peut ainsi return EXIT_SUCCESS ou EXIT_FAILURE au systeme d'exploitation). Remarque egalement que dans le bout de code que tu donnes, le prototype de loadTextFile() est inconnu par main(). Ton compilateur doit signaler cet oubli. Il manque egalement les en-tetes stdio.h et stdlib.h. Comme tu castes realloc() [ce qui est mal en C], cela signifie que realloc() est supposee retourner un int, non un void *, ce qui cause probablement tes problemes de segmentation fault.

    Citation Envoyé par ramislebob
    qu'est ce que tu entends par "réclamer de la mémoire" ? est il possible de connaitre la mem disponnible ?
    Non, c'est a toi de creer tout un mecanisme de garbage collection (comptage de reference par exemple). C'est ce que j'appelle un 'mecanisme plus sophistique'. Pour l'instant, contente toi de faire un free() si realloc() echoue [ce que je fais la plupart du temps, en fait!].

  10. #10
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    Citation:
    homeostasie a écrit :

    ...
    char *confSrc = malloc(NbCaract * sizeof(*confSrc));
    loadTextFile(fichierConf, confSrc);
    ...

    void loadTextFile(char *name, char *stockage)
    {
    ...
    }

    ben il me semble que ça ne va pas. Pour modifier un char * dans une fonction il faut lui passer en param un pointeur sur ce char *...
    En effet, c'est cela qui est fait!
    En gros, on pourrait dire que ca correspond à cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *stockage = confSrc;
    Ce qui signifie que stockage reçoit l'adresse de "confSrc" et donc pointe sur le début de ta chaîne de caractère "confSrc".

    Pas compris ce que tu veux dire. *stockage est un char *, l'adresse du début de mon string. stockage est un pointeur sur mon string.
    Ben non, *stockage est un char et non un char*! stockage est l'adresse de début de ton string et *stockage représente le premier caractère de ta chaîne.

  11. #11
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    est il possible de connaitre la mem disponnible ?
    Oui ca l'est en utilisant des variables et/ou fonctions spécifiques au noyau. Le mieux c'est d'avoir accès aux fichiers sources.
    Sinon il faut redéfinir ses propres fonctions (malloc, calloc, realloc, free) pour connaître la mémoire totale utilisée,libérée et donc restante. Mais dans ton cas, je ne pense pas que cela a de l'importance.

    Juste comme cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    strncat(*stockage,buffer,NbLu);
    (*stockage)[taille-1]=0x0;
    Pas besoin de mettre à 0 après l'utilisation de strncat.
    strncat() recopie au plus 'len' caractères de la chaîne 'sce' à la fin de 'dest', puis y ajoute un caractère '\0'.

  12. #12
    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 DaZumba
    De plus, c'est quoi 0x0 ? Autant utiliser NULL ou 0, au moins on est sur que le compilateur mettre bien le pointeur a l'adresse invalide correspondant a NULL, qui n'est pas forcement 0x0.
    Hum, non. Dans un contexte pointeur, char *p = 0 et char *p = NULL sont strictement équivallents. L'usage de NULL est purement documentaire. (comme '\0' vs 0 pour les fins de chaines).

    Ce qu'on a pas le droit de faire, c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
       char *p;
     
       memset (&p, 0, sizeof p);
    en croyant faire p = 0. Ce n'est pas portable, car p = 0 ne veut pas forcément dire 'mettre tous les bits à 0'.

    Avec char p = 0, comme on est dans un contexte 'pointeur', le compilateur sait ce qu'il a à faire. (Si ça se trouve, il va écrire 0x80000000 dans le pointeur, qui sait...)

  13. #13
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Hum, non. Dans un contexte pointeur, char *p = 0 et char *p = NULL sont strictement équivallents. L'usage de NULL est purement documentaire. (comme '\0' vs 0 pour les fins de chaines).
    Oui, mon interrogation etait plus sur '0x0 est-il egal a 0 et est-il interprete par le compilateur comme NULL en contexte pointeur ?'. Je ne sais pas cela...

  14. #14
    Membre confirmé

    Inscrit en
    Janvier 2006
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 188
    Par défaut
    Citation Envoyé par ramislebob
    Quand j'initialise mon char* à NULL, plantage :s
    en revanche un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        char *confSrc = (char *) malloc(1);
        confSrc[0]=0x0;
    permet une initialisation à vide.
    bref, realloc semble ne s'appliquer QUE à un espace mémoire alloué par malloc.
    Sous Windows, un n'est pas équivalent au malloc ci-dessus si on utilise des realloc après !
    l'initialisation à NULL (ou 0x0) provoque un plantage de la CMD...


    Citation Envoyé par Emmanuel Delahaye
    Il faut vérifier si malloc() a réussi avant d'utiliser le bloc alloué.
    oups... j'ai oublié de mettre de la robustesse la-dessus :s
    que peut on faire quand on a un échec sur un malloc ou un realloc ? (à part retester n fois)
    je repose ma question : cé koi que vous appelez cast ?

  15. #15
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    Sous Windows, un
    n'est pas équivalent au malloc ci-dessus si on utilise des realloc après !
    l'initialisation à NULL (ou 0x0) provoque un plantage de la CMD...
    Si tu parles de programmation window orienté C++, le malloc est l'équivalent d'un new et le free d'un delete.

    L'écriture que tu as faîte signifie que ton pointeur pointe sur une valeur non valide. C'est cela qu'il faut faire quand tu ne désires pas encore pointer sur une adresse spécifique ou si tu n'as pas encore besoin d'allouer un espace mémoire.

    remarque:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *confSrc = (char *) malloc(1);
    Vaut mieux faire cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char *confSrc = malloc(sizeof(*confSrc));

  16. #16
    Membre confirmé

    Inscrit en
    Janvier 2006
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 188
    Par défaut
    Citation Envoyé par homeostasie
    Si tu parles de programmation window orienté C++, le malloc est l'équivalent d'un new et le free d'un delete.
    nan j'ai jamais fais de C++, uniquement du C.

    Citation Envoyé par gege2061
    Si ça plante, c'est surement que tu as un débordement quelque part qui écrase les structures de données internes servant à gérer la mémoire.
    ben je comprends pas où alors :s
    je vais remettre mon code au complet, si quelqu'un peut me dire pourquoi quand je met un NULL au lieu d'un malloc ça plante...
    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
     
    #ifdef __cplusplus
        #error Be sure you are using a C compiler...
    #endif
     
    #ifndef WIN32
        #define WIN32
    #endif
     
    #ifndef RENFOTO
        #define RENFOTO
        #include <stdio.h> 
        #include <stdlib.h>
        #include <sys/types.h>
        #include <errno.h> // perror
        #include <strings.h> // strlen, strcpy,...
        #include <string.h> // bzero...
        #include <unistd.h> // R_OK
        #include <fcntl.h> // O_RDONLY O_WRONLY
    #endif
     
    #ifdef WIN32
        #include <windows.h>
    #endif
     
     
    #define filePath "C:\\blabla.txt"
     
    int existFile(char *fichier);
    int myRealloc(void ** ppData, size_t newSize);
    void loadTextFile(char *name, char **stockage);
     
    // Fonction Principale :p
    int main(int argc, char *argv[], char **envp){
        char *fichier=NULL;//(char *) malloc(1);
    //    fichier[0]=0x0;
        loadTextFile(filePath, &fichier);  
        printf("%s",fichier);
        free(fichier);
        exit(0);
    }
     
    /** Test d'existance d'un fichier */
    int existFile(char *fichier){
     
        if ( access(fichier, F_OK)==-1 ){
            printf("Error Access File : %s :\\\n",fichier);
            return -1;
        }
        else
            return 0;
    }
     
    int myRealloc(void ** ppData, size_t newSize){
        void *pTmp = realloc(*ppData, newSize);
        if(pTmp == NULL)
    	return -1;	
        else{
    	*ppData = pTmp;
    	return 0;
        }
    }
     
    void loadTextFile(char *name, char **stockage){
        #define tailleBuffer 10
        char buffer[tailleBuffer];
        FILE *file;
        int NbLu;
        int taille=strlen(*stockage);
    //    printf("TAille initiale : %i\n",taille);
     
        if (existFile(name)==-1){
    	printf("Accès impossible au fichier %s...\n",name);
    	printf("Existe t'il vraiment... :s");
    	exit(1);
        }
     
        if((file=fopen(name, "r")) == NULL){
    	printf("Ouverture impossible du fichier %s :s\n",name);	
    	exit(1);
        }
     
        while( (NbLu=fread(buffer, 1, tailleBuffer, file)) != 0){
    	taille+=NbLu;
    	if (myRealloc((void **)stockage,taille+1)==-1){
    	    free(*stockage);
    	    printf("Error Realloc :s\n");
    	    exit(1);
    	}
    //	*stockage=(char *) realloc(*stockage,taille+1);
    	strncat(*stockage,buffer,NbLu);
    	(*stockage)[taille-1]=0x0;
        }
        fclose(file);
    }
    Pourquoi ça fait planter la CMD ?

  17. #17
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Par défaut
    Citation Envoyé par ramislebob
    Sous Windows, un n'est pas équivalent au malloc ci-dessus si on utilise des realloc après !
    l'initialisation à NULL (ou 0x0) provoque un plantage de la CMD...
    Ah si ! Ce genre de chose est utilisé dans les boucles, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    char *text = NULL;
    size_t size = 1;
     
    while (/* ... */)
    {
      void *tmp = NULL;
     
      size <<= 2;
      tmp = realloc (text, sizeof (*text) * size)
      if (tmp)
      {
        text = tmp;
      }
    }
    Si ça plante, c'est surement que tu as un débordement quelque part qui écrase les structures de données internes servant à gérer la mémoire.

    Un cast c'est la même chose qu'un transtypage.

  18. #18
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Citation Envoyé par ramislebob
    que peut on faire quand on a un échec sur un malloc ou un realloc ? (à part retester n fois)
    C'est une erreur fatale et on doit quitter le programme (sauf utilisation de techniques sophistiquees inutiles dans ton cas).

    je repose ma question : cé koi que vous appelez cast ?
    Merci d'eviter le SMS: 'qu'appelez-vous un cast?' (ou transtypage, pour etre pedant).
    C'est forcer un changement de type d'une variable, d'un retour de fonction, etc.
    malloc() renvoit un void * que tu castes en (char *). En C, c'est mal, car c'est inutile (tout pointeur void est conforme a un pointeur de n'importe quel type) et cela cache la non-inclusion de stdlib.h.

  19. #19
    Membre confirmé

    Inscrit en
    Janvier 2006
    Messages
    188
    Détails du profil
    Informations forums :
    Inscription : Janvier 2006
    Messages : 188
    Par défaut
    Citation Envoyé par DaZumba
    C'est une erreur fatale et on doit quitter le programme (sauf utilisation de techniques sophistiquees inutiles dans ton cas).


    Merci d'eviter le SMS: 'qu'appelez-vous un cast?' (ou transtypage, pour etre pedant).
    C'est forcer un changement de type d'une variable, d'un retour de fonction, etc.
    malloc() renvoit un void * que tu castes en (char *). En C, c'est mal, car c'est inutile (tout pointeur void est conforme a un pointeur de n'importe quel type) et cela cache la non-inclusion de stdlib.h.
    sorry pour le langage SMS :s
    je savais pas qu'un transtypage s'appelle un cast :s (ça me fais penser à diffusion, je vois pas trop le rapport avec un transtypage..)

  20. #20
    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 ramislebob
    Sous Windows, un n'est pas équivalent au malloc ci-dessus si on utilise des realloc après !
    l'initialisation à NULL (ou 0x0) provoque un plantage de la CMD...
    Jamais constaté ça. Montre le code qui a ce comportement.
    oups... j'ai oublié de mettre de la robustesse la-dessus :s
    que peut on faire quand on a un échec sur un malloc ou un realloc ? (à part retester n fois)
    On peut effectivement recommencer un peu plus tard (sleep(), Sleep(), selon le système...). En cas d'echec définitif, remonter l'info aux couches supérieures qui prendront les décisions qui s'imposent. Ca dépend qui et impliqué.
    je repose ma question : cé koi que vous appelez cast ?
    Je crois qu'on t'a déjà répondu : conversion d'un type dans un autre. C'est rarement utile et souvent le signe d'un codage de chacal.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 3
    Dernier message: 15/06/2010, 22h11
  2. Programmer encore en VB 6 c'est pas bien ? Pourquoi ?
    Par Nektanebos dans le forum Débats sur le développement - Le Best Of
    Réponses: 85
    Dernier message: 10/03/2009, 14h43
  3. Réponses: 4
    Dernier message: 03/12/2002, 16h47
  4. [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
  5. Allocation de ressources
    Par Eric Pasquier dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 08/10/2002, 09h19

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