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 :

fopen non correct


Sujet :

C

  1. #1
    Membre confirmé
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Mars 2014
    Messages
    158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur sécurité

    Informations forums :
    Inscription : Mars 2014
    Messages : 158
    Points : 465
    Points
    465
    Par défaut fopen non correct
    bonjours à tous.

    je suis actuellement en train de développer un petit serveur de sauvegarde de fichier (texte et binaire) mais je me retrouve avec un problème (je suppose que vous vous en doutez ^^)

    mon problème est :
    j'ai une fonction qui est doit m'ouvrir un fichier en écriture et faire des test dessus pour vérifier qu'il n'y as pas eu d'erreur lors de l'ouverture car le nom de fichier est dynamique.
    les paramètres sont le nom du fichier (char *) et son dossier (char *) cependant lors de la création du fichier celui ci se retrouve avoir un nom tronqué à 4 caractère. de plus si je tente de fermer le fichier je me retrouve avec une erreur de free m'indiquant que le pointeur du fichier est incorect (c'est ce que j'en ais déduis)...
    ci-dessous je vous joint le code de la fonction (le fclose est la juste pour tester l'erreur il n'est pas présent dans la vraie version)

    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
    FILE *RFopen(char *nomFichier,char *dossier){
     
    char *location=strdup(dossier);
    FILE *fichier;
    strcat(location,nomFichier);
        printf("localisation : '%s'\n",location);
        fichier=fopen(location,"wb");
        if (fichier==NULL) {
        perror("fopen()");
        exit(errno);
        }else{
        printf("Fichier ouvert: %s \nDans %s\n",nomFichier,dossier);}
        fclose(fichier);
        return fichier;
    }
    /** \brief ouverture d'un fichier en mode binaire
     * \param nom du fichier
     * \param dossier de stockage du fichier
     * \return file descriptor
     */
    merci d'avance

  2. #2
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut
    Bonsoir
    Concrètement tu as des adresses invalides.
    Attention à l'utilisation de la fonction "strdup" elle retourne nulle quand elle n'a pas assez de mémoire pour effectuer le traitement de la chaîne ou de la sous-chaîne. il faut également faire attention à la concaténation comment pourrais-tu savoir si cela a bien fonctionné ? Et pourquoi vouloir créer et tester un fichier sans écrire dedans ?
    Le mieux serait de savoir si des données à traiter existent et dans ce cas on crée le fichier pour pouvoir le manipuler dans le cas contraire, on ne fait rien
    exemple ( exemple pas optimisé à s'en n'inspirer pour faire une adaptation ou une correction ).
    à bientôt
    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
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    void f_WriteData( const char *p_src, const char *p_dst, const char *p_data ){
     
    	char *ptr = NULL;
    	FILE *pFile = NULL;
     
    	if( (p_src == NULL) || (p_data == NULL) ){
    		fprintf( stderr,"Aucun non de fichier ou donnée disponible\n");
    		exit( EXIT_FAILURE );
    	}
    	else if( (p_src != NULL) && (p_dst == NULL) ){
    		pFile = fopen( p_src, "a+" );
    		if( pFile == NULL ){
    			perror("Erreur ouverture du fichier\n");
    			exit( EXIT_FAILURE );
    		}
    	}
    	else{
    		ptr = (char*)calloc( (sizeof(p_src)+sizeof(p_dst) ) +2, sizeof(char) );
    		if( ptr == NULL ){
    			perror("Erreur allocation de sauvergarde\n");
    			exit( EXIT_FAILURE );
    		}
     
    	#if __STDC_VERSION__ >= 199901L
    			if( ! snprintf( ptr, sizeof(ptr), "%s%s%s", p_dst,"/", p_src ) ){
    				free( ptr );
    				ptr = NULL;
    				perror("Echec de la concaténation\n");
    				exit( EXIT_FAILURE );
    			}
    	#else
    			if( strcat( ptr, p_dst ) != NULL ){
    				if( strcat( ptr, "/" ) != NULL ){
    					if( NULL == strcat( ptr, p_src ) ){
    						free( ptr );
    						ptr = NULL;
    						perror("Impossible de faire une concaténation\n");
    						exit( EXIT_FAILURE );
    					}
    				}else{
    					free( ptr );
    					ptr = NULL;
    					perror("Impossible de faire une concaténation\n");
    					exit( EXIT_FAILURE );
    				}
    			}else{
    				free( ptr );
    				ptr = NULL;
    				perror("Echec de la concaténation\n");
    				exit( EXIT_FAILURE );
    			}
    	#endif
     
    		pFile = fopen( ptr, "a+" );
    		if( pFile == NULL ){
    			free( ptr );
    			ptr = NULL;
    			perror("Erreur ouverture du fichier\n");
    			exit( EXIT_FAILURE );
    		}
    	}
     
    	/* Ecriture des des données */
    	if( fputs( p_data, pFile) == EOF ){
    		free( ptr );
    		perror("Erreure écriture des données\n");
    		ptr = NULL;
    	}
     
    	fclose( pFile );
    	free( ptr );
    	ptr = NULL;
    }
     
    int main( void ){
     
    	f_WriteData("Coucou.txt", "Teste","Bonjours\n" );
    	return( EXIT_SUCCESS );
    }
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  3. #3
    Membre confirmé
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Mars 2014
    Messages
    158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur sécurité

    Informations forums :
    Inscription : Mars 2014
    Messages : 158
    Points : 465
    Points
    465
    Par défaut
    pour ta question sur pourquoi crée le fichier sans rien écrire dedans:

    il se trouve que pour rendre mon code lisible et ré-adaptable (c'est aussi pour ça que je mets des commentaire après chacune de mes fonctions ^^) au besoin j’essaie de rendre mes fonctions avec très peu de code dedans et un code spécifique (j’entends par la une fonction travaillant sur un fichier ne touche pas à un socket et inversement enfin quand c'est possible)

    en fin le but de la fonction est juste de m'ouvrir un fichier en écriture pour que ce fichier sois remplie dans la fonction qui l'as appeler (pour te donner une idée je mets le code de la fonction l'appelant)

    pour info Drecv est une fonction qui reçoit des donnée que le client lui as envoyer (un peu comme recv mais elle fait une vérification avec le client sur les donnée (enfin c'est pas encore bien implémenter mais c'est prévue))

    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
       void frecv(SOCKET csock,char *dossier){
        int ctrl=0;
        char buffer[BUFFERSIZE];
        char nomFichier[BUFFERSIZE];
        Drecv(nomFichier,csock);
        FILE *fichier=RFopen(nomFichier,dossier);
        while(ctrl>0)
       {
        ctrl=Drecv(buffer,csock);
        if(ctrl==3){
        if(!strcmp(buffer,"EOF")){ /* EOF est envoyer en tant que caractère à la fin de l'envoie du fichier il s'agit des 3 caractères E,O,F et non -1 */ 
                printf("\nEnd of file!!!\n");
                break;
        }else{
        fwrite( buffer , sizeof(buffer[0]) , sizeof(buffer)/sizeof(buffer[0]) , fichier);
        }
        }
        else{
        fwrite( buffer , sizeof(buffer[0]) , sizeof(buffer)/sizeof(buffer[0]) , fichier);
            }
       }
        fclose(fichier);
    }
    /** \brief reception d'un fichier
     * nom + corp
     * \param socket sur lequel ecouter
     * \param dossier ou stocker le fichier
     * \return void
     */
    pour ton code j'en vais m'en inspirer pour faire mes vérifications si ça te dérange pas

    effectivement je ne check pas encore si la concaténation est bonne (je suis autodidacte en C donc j'ai pas mal de chose que je devrais savoir que je ne sais pas ^^) mais c’était pour ça que je fais un printf (je suis encore encore en phase de dev et je me doute que ce n'est pas une super vérification mais je viens juste de me mettre à gérer ce genre de problème donc je n'ai pas encore vraiment l'habitude avec ce genre de chose)

    P.S merci pour ta réponse rapide

  4. #4
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut
    Bonsoir
    Citation Envoyé par Comandant Chaos Voir le message
    pour ta question sur pourquoi crée le fichier sans rien écrire dedans:

    il se trouve que pour rendre mon code lisible et ré-adaptable (c'est aussi pour ça que je mets des commentaire après chacune de mes fonctions ^^) au besoin j’essaie de rendre mes fonctions avec très peu de code dedans et un code spécifique (j’entends par la une fonction travaillant sur un fichier ne touche pas à un socket et inversement enfin quand c'est possible)

    en fin le but de la fonction est juste de m'ouvrir un fichier en écriture pour que ce fichier sois remplie dans la fonction qui l'as appeler (pour te donner une idée je mets le code de la fonction l'appelant)
    Je pense concrètement que tu n'as rien compris de ce que j'avais écrit et si c'est le cas, je m'en excuse d'avance. J'essayais de te faire comprendre ici, que l'on travaille sur un ou des fichiers à condition que des données existent et quand peut par la suite les manipuler pour effectuer de divers traitements par exemple, une sauvegarde.
    Et à ce que je sache en ne touche pas a ta fameuse histoire de socket et que veux-tu réadapter de plus à ton programme l'écriture ou la lecture, la façon de les écrire peut-être ou tout simplement une méthode révolutionnaire de traitement de fichier . . ?

    Monseigneur, quand t'en crée un où des fichiers, c'est pour traiter les informations dans le but de les sauvegarder ou lire.

    Un fichier en anglais "file" est une suite d’informations, enregistrées sur un support physique et identifié par un nom. par lequel les manipulations peuvent être la création d'un fichier donc le déclarer pour qu’il existe et l’initialiser ou savoir s'il existe dans ce cas en effectuer de différentes tâches avec, exemple: écriture ou lecture donc lire ou écrire des informations sinon à quoi peut-il servir ?
    modifier certaines données, le détruire dans le cas où il a plus d'utilité.

    Citation Envoyé par Comandant Chaos Voir le message
    pour info Drecv est une fonction qui reçoit des donnée que le client lui as envoyer (un peu comme recv mais elle fait une vérification avec le client sur les donnée (enfin c'est pas encore bien implémenter mais c'est prévue))

    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
       void frecv(SOCKET csock,char *dossier){
     
        Drecv(nomFichier,csock);
        FILE *fichier=RFopen(nomFichier,dossier);
        while(ctrl>0)
       {
        ctrl=Drecv(buffer,csock);
        ........
        fwrite( buffer , sizeof(buffer[0]) , sizeof(buffer)/sizeof(buffer[0]) , fichier);
        }
        }
        else{
        fwrite( buffer , sizeof(buffer[0]) , sizeof(buffer)/sizeof(buffer[0]) , fichier);
            }
       }
        fclose(fichier);
    }
    /** \brief reception d'un fichier
     * nom + corp
     * \param socket sur lequel ecouter
     * \param dossier ou stocker le fichier
     * \return void
     */
    P.S merci pour ta réponse rapide
    je lâche l'affaire monseigneur @Comandant Chaos , car je suis K.O et donc je vais me coucher
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  5. #5
    Membre confirmé
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Mars 2014
    Messages
    158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur sécurité

    Informations forums :
    Inscription : Mars 2014
    Messages : 158
    Points : 465
    Points
    465
    Par défaut
    bonjour,

    après relecture de tes deux post je pense avoir compris ce que tu veux me dire :
    Le mieux serait de savoir si des données à traiter existent et dans ce cas on crée le fichier pour pouvoir le manipuler dans le cas contraire, on ne fait rien
    si j'ai bien compris tu me conseillerais au lieu de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    appeler ma  fonction qui ouvre mon fichier 
    remplir entièrement mon fichier dans la fonction appelante grâce aux donnée du socket.
    fermer ce fichier dans la fonction appelante
    plus qu'elle que chose comme ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    vérifier que des donnée existe sur mon socket
    si non on ne fait rien
    si oui j'ouvre mon fichier 
    j’écris mon bloc de donnée en mode apending
    je ferme le fichier
    et je boucle sur ces opérations tant que le contenue du socket est différent de ma marque de fin de fichier
    est ce ça que tu veux me faire comprendre ?

  6. #6
    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ...
    char *location=strdup(dossier);
    FILE *fichier;
    strcat(location,nomFichier);
    ...
    strdup() alloue de la mémoire pour stocker un duplicata de la chaine dossier. Il n'y a pas de place pour y ajouter avec le strcat() la chaine nomFichier. Tu obtiens un dépassement du buffer location avec un comportement indéterminé. Le programme doit être dès ce stade considéré comme détruit.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

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

  7. #7
    Membre confirmé
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Mars 2014
    Messages
    158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur sécurité

    Informations forums :
    Inscription : Mars 2014
    Messages : 158
    Points : 465
    Points
    465
    Par défaut
    @diogene
    si j’aie bien compris ce que tu me dis il faut que je fasse un realloc ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    char *location=strdup(dossier);
    FILE *fichier;
    realloc(location,sizeof(location)+sizeof(nomFichier));
    strcat(location,nomFichier);
    cependant après test il se trouve que j'ai la même erreur .
    je fais une mauvaise utilisation de realloc?

  8. #8
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut
    Bonjour
    Ce que @diogene essaie de te dire et qu'il a très bien résumé la chose, est que la fonction strdup() alloue de la mémoire suffisante pour contenir la copie de ta chaîne de caractères et que la fonction strcat() quant a elle ne peut effectuer une concaténation, car il n'y a pas d'espace mémoire nécessaire au traitement des deux chaînes de caractères. En clair tu fais un dépassement de mémoire donc ton pointeur devient invalide et c'est un peu ce que j'ai essaye de te faire comprendre et t'orienter "hier" afin que tu puisses corriger ton erreur par toi même, mais aussi revoir la façon dont tu manipule ton fichier et comme tu à rien voulu savoir, moi j'ai lâché l'affaire.
    Par curiosité comprends-tu au moins ce que tu écris comme programme ? renseignes-toi sur la fonction d'allocation, relocation et de libération mémoire et tu sauras d'où vient ton erreur.
    à bientôt
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  9. #9
    Membre confirmé
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Mars 2014
    Messages
    158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur sécurité

    Informations forums :
    Inscription : Mars 2014
    Messages : 158
    Points : 465
    Points
    465
    Par défaut
    @sambia39 je n’essaie pas de mettre de la mauvaise volonté au contraire j’essaie de comprendre ce que vous m'expliquez (comme je l'ai dis j'ai surement des lacunes mais j’essaie de les combler) et de m'en inspirez excuse moi si tu ne l'avais pas compris comme ça

    je pense avoir bien compris le fonctionnement des fonctions malloc, realloc, free qui alloue un espace mémoire ou le libère et je pense avoir compris ce que fait strdup() (corrigez moi si je me trompe)

    elle crée un pointeur et lui alloue une espace mémoire de sizeof(char)*sizeof(tableau de caractère passer en paramètre) puis copie le tableau de char dans ce nouvel espace.

    ex si je fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *tab=strdup("0123456789");
    je vais allouer à mon pointeur un espace mémoire de sizeof(char)*sizeof(machaine)=4*11=41bits
    puis le remplir par la chaine 0123456789\0
    est ce que j'ai tord?
    si je te suis si je fais maintenant un strcat je suis hors de ma zone mémoire car je remplace mon \0 par un caractère (je suis encore dans mon espace memoire) puis j’essaie d'en rajouter un mais là je dépasse mes 44bits donc je pars en segmentation error car j’essaie d’écrire dans un espace mémoire non alloué.
    corrigez moi si j'ai tord.

    c'est pour cette raison que je pensais à un realloc
    ex
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char *tab=strdup("0123456789");/* j'alloue 11*4 bits pour mon tableau*/
    char *tab2="ABCDEF"; /* j'alloue 7*4 bits pour mon tableau*/
    realloc(tab,sizeof(char)*(sizeof(tab)+sizeof(tab2))) /* j'alloue 4*(11+7)=44+28=72bit pour tab non?*/
    /*dans ce cas je devrai avoir la place de copier tab2 à la suite de tab?*/
    donc si je revient à mon code original
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char *location=strdup(dossier);/* j'alloue la même taille que dossier ex: dossier fait 12 char j'ai alors 12*4 bit d'allouer pour mon pointeur*/
    FILE *fichier;
    realloc(location,sizeof(char)*(sizeof(location)+sizeof(nomFichier)));/* je re-alloue 4*(12+X)bits non?*/
    /*dans ce cas strcat est correct non? */
    strcat(location,nomFichier);

  10. #10
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut
    Citation Envoyé par Comandant Chaos Voir le message
    je pense avoir bien compris le fonctionnement des fonctions malloc, realloc, free qui alloue un espace mémoire ou le libère et je pense avoir compris ce que fait strdup() (corrigez moi si je me trompe)

    elle crée un pointeur et lui alloue une espace mémoire de sizeof(char)*sizeof(tableau de caractère passer en paramètre) puis copie le tableau de char dans ce nouvel espace.
    ......
    si je te suis si je fais maintenant un strcat je suis hors de ma zone mémoire car je remplace mon \0 par un caractère (je suis encore dans mon espace memoire) puis j’essaie d'en rajouter un mais là je dépasse mes 44bits donc je pars en segmentation error car j’essaie d’écrire dans un espace mémoire non alloué.
    corrigez moi si j'ai tord.

    c'est pour cette raison que je pensais à un realloc
    ex
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char *tab=strdup("0123456789");/* j'alloue 11*4 bits pour mon tableau*/
    char *tab2="ABCDEF"; /* j'alloue 7*4 bits pour mon tableau*/
    realloc(tab,sizeof(char)*(sizeof(tab)+sizeof(tab2))) /* j'alloue 4*(11+7)=44+28=72bit pour tab non?*/
    /*dans ce cas je devrai avoir la place de copier tab2 à la suite de tab?*/
    donc si je revient à mon code original
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char *location=strdup(dossier);/* j'alloue la même taille que dossier ex: dossier fait 12 char j'ai alors 12*4 bit d'allouer pour mon pointeur*/
    FILE *fichier;
    realloc(location,sizeof(char)*(sizeof(location)+sizeof(nomFichier)));/* je re-alloue 4*(12+X)bits non?*/
    /*dans ce cas strcat est correct non? */
    strcat(location,nomFichier);
    Tu n'as pas tort sur la réallocation de la mémoire et si tu as compris le principe sur les allocations et réallocation mémoire, tu n'aurais pas une erreur.
    Partons de la remarque de @diogene et teste les codes ci-dessous.
    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
     
    #define _GNU_SOURCE 1
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int main( void ){
     
    	char *ptr = NULL;
    	ptr = strdup("joh la tringlette");
    	realloc( ptr, sizeof(ptr)*50 );
    	strcat( ptr, " Alias le baron" );	/*** buffer overflow ***/
    	free( ptr );
     
    	return( EXIT_SUCCESS );
    }
    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
     
    #define _GNU_SOURCE 1
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int main( void ){
     
    	char *ptr = NULL;
    	char *p_alias = NULL;
    	ptr = strdup("joh la tringlette");
    	if( ptr == NULL ){
    		perror("Erreur allocation mémoire\n");
    		exit( EXIT_FAILURE );
    	}
    	p_alias = realloc( ptr, sizeof(ptr)*50 );
    	if( p_alias == NULL ){
    		free( ptr );
    		ptr = NULL;
    		perror("Erreur reallocation\n");
    		exit( EXIT_FAILURE );
    	}
    	ptr = p_alias;
    	strcat( ptr, " Alias le baron" );
    	printf("%s\n", ptr );
    	free( ptr );
    	ptr = NULL;
     
    	return( EXIT_SUCCESS );
    }
    À tu compris pourquoi ton code ne marche toujours pas ?
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  11. #11
    Membre confirmé
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Mars 2014
    Messages
    158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur sécurité

    Informations forums :
    Inscription : Mars 2014
    Messages : 158
    Points : 465
    Points
    465
    Par défaut
    merci je viens enfin de comprendre mon erreur .
    si j'ai bien compris c'est que je gardais l'ancienne adresse du pointeur (donc l'ancienne allocation de mémoire pour mon pointeur ) au lieu de prendre la nouvelle.
    de plus je me trompais avec sizeof qui ne donne pas la taille de la chaine mais la taille du pointeur il faut utiliser strlen pour ca...

    du coup j'ai modifier mon code pour rajouter les vérification (je me suis basée sur les tiennes )

    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
    FILE *RFopen(char *nomFichier,char *dossier){
     
    char *location=strdup(dossier);
    	if( location == NULL ){
    		perror("Erreur allocation mémoire\n");
    		exit( EXIT_FAILURE );
    	}
    char *ptr_loc=NULL;
    FILE *fichier;
     
    ptr_loc=realloc(location,sizeof(char)*(strlen(location)+strlen(nomFichier)));
    if( ptr_loc == NULL ){
    		free( location );
    		location = NULL;
    		perror("Erreur reallocation\n");
    		exit( EXIT_FAILURE );
    	}
    location=ptr_loc;
     
    strcat(location,nomFichier);
     
        printf("localisation : '%s'\n",location);
        fichier=fopen(location,"wb");
        if (fichier==NULL) {
        perror("fopen()");
        exit(errno);
        }else{
        printf("Fichier ouvert: %s \nDans %s\n",nomFichier,dossier);}
        return fichier;
    }
    /** \brief ouverture d'un fichier en mode binaire
     * \param nom du fichier
     * \param dossier de stockage du fichier
     * \return file descriptor
     */
    De plus un grand merci à vous deux pour avoir été patient avec moi

  12. #12
    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char *location=strdup(dossier);/* j'alloue la même taille que dossier ex: dossier fait 12 char j'ai alors 12*4 bit d'allouer pour mon pointeur*/
    FILE *fichier;
    realloc(location,sizeof(char)*(sizeof(location)+sizeof(nomFichier)));/* je re-alloue 4*(12+X)bits non?*/
    /*dans ce cas strcat est correct non? */
    strcat(location,nomFichier);
    Le realloc() est faux :
    1- Qu'est-ce que location ? un char* . Qu'est-ce que nomFichier ? un char * . Alors la ligne du realloc() est équivalente à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    realloc(location,sizeof(char)*(sizeof(char*)+sizeof(char*)));/* je re-alloue 4*(12+X)bits non?*/
    soit comme sizeof(char) vaut toujours 1 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    realloc(location,2*sizeof(char*));/* je re-alloue 4*(12+X)bits non?*/
    Ce qui n'a rien à voir avec la longueur des chaines à stocker (qui elle s'obtient avec strlen()).

    2- Une reallocation peut changer la place allouée et dans ce cas location, qui conserve sa valeur d'avant l'appel à realloc(), contient une adresse qui n'est plus valide. Au minimum, on doit avoir location = realloc(location,......). Toutefois, la reallocation pouvant échouer et alors renvoyer NULL, si on fait cela, on perd la valeur de location ce qui entraine une fuite mémoire. Le schéma à suivre est

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    p = realloc(location,.....);
    if(p==NULL)
    { // traiter l'échec de la réallocation, éventuellement en récupérant la mémoire allouée 
    }
    else
    { 
     location = p ;
     // continuer
     ....
    }
    Pourquoi utiliser une reallocation et ne pas plutôt allouer directement la quantité qu'il faut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char * location = malloc(strlen(dossier) + strlen(nomFichier)+1);
    if(location != NULL)
    {
       strcpy(location, dossier) ;
       strcat(location, nomFichier);
      ....
    Publication : Concepts en C

    Mon avatar : Glenn Gould

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

  13. #13
    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
    Tu as fait pas mal de corrections pendant que je te répondais.

    Il reste une erreur ici
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ptr_loc=realloc(location,sizeof(char)*(strlen(location)+strlen(nomFichier)));
    car tu as oublié de compter le '\0' terminal (voir mon post précédent)
    Publication : Concepts en C

    Mon avatar : Glenn Gould

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

  14. #14
    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
    Pour commencer, si tu tiens à concaténer dynamiquement à une chaîne tu devrais faire une fonction dédiée à cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int concat(char **ppDynamicStr, char const *str)
    {
    	size_t totalLength = strlen(*ppDynamicStr) + strlen(str);
    	size_t totalSize = totalLength + 1;
    	char *pNew = realloc(*ppDynamicStr, totalSize);
    	if(pNew == NULL)
    		return -1;
     
    	*ppDynamicStr = pNew;
    	strcat(pNew, str);
    	return 0;
    }
    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.

  15. #15
    Membre confirmé
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Mars 2014
    Messages
    158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur sécurité

    Informations forums :
    Inscription : Mars 2014
    Messages : 158
    Points : 465
    Points
    465
    Par défaut
    @diogene j'avoue j'avais oublier que je supprimais un des deux \0 cependant il s'agit plus d'une optimisation que d'un bug étant donnée que le dernier caractère ne seras jamais lue vu que l'avant dernier est \0 (a moins de boucler sur une incrémentation de pointeur et de lire après le \0 mais c'est dangereux et ça risque de partir en seg error)

    @Médinoc je note ton code merci mais la concaténation est utilisé qu'aux moment de la réception du nom de fichier le reste du programme n'effectue pas d'opération sur les caractères donc crée une fonction est un peu lourds non?
    cependant je n’aie pas très bien compris ton usage du tableaux de pointeur (pourquoi n'utilise tu pas tout simplement un char * ? je n'ais pas trouvé de justification dans ton code ...)

    P.S il se trouve aussi que maintenant que j’aie corriger cette fonction mon début de serveur fonctionne mais à un bug logique lors de la réception j'ai ouvert un post dans le sous forum réseau si jamais vous avez la bonté d’âme de m'aider je vous en serait reconnaissant

  16. #16
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Créer une fonction n'est jamais lourd.

    Il est plus clair de lire la fonction utilisant la concaténation si elle ne contient pas le code en lui-même.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  17. #17
    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
    Citation Envoyé par Tagashy Voir le message
    @Médinoc je note ton code merci mais la concaténation est utilisé qu'aux moment de la réception du nom de fichier le reste du programme n'effectue pas d'opération sur les caractères donc crée une fonction est un peu lourds non?
    cependant je n’aie pas très bien compris ton usage du tableaux de pointeur (pourquoi n'utilise tu pas tout simplement un char * ? je n'ais pas trouvé de justification dans ton code ...)
    Il n'y a pas de tableau de pointeurs ici, seulement un pointeur vers un pointeur... nécessaire parce que la fonction modifie le pointeur en question (à cause de realloc).

    Exemple d'utilisation:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char* toto = strdup("toto");
    concat(&toto, "tata");
    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.

  18. #18
    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
    @diogene j'avoue j'avais oublier que je supprimais un des deux \0 cependant il s'agit plus d'une optimisation que d'un bug étant donnée que le dernier caractère ne seras jamais lue vu que l'avant dernier est \0 (a moins de boucler sur une incrémentation de pointeur et de lire après le \0 mais c'est dangereux et ça risque de partir en seg error)
    Je n'ai pas trop compris ce que tu veux dire mais à la lecture du code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    char *location=strdup(dossier);
    ...
    ptr_loc=realloc(location,sizeof(char)*(strlen(location)+strlen(nomFichier)));
    if( ptr_loc == NULL ){
    ...
    location=ptr_loc;
    strcat(location,nomFichier);
    le +1 dans le realloc() est impératif, ce n'est pas une optimisation.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

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

  19. #19
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 543
    Points : 1 745
    Points
    1 745
    Par défaut
    Bonjour
    Citation Envoyé par Médinoc Voir le message
    Pour commencer, si tu tiens à concaténer dynamiquement à une chaîne tu devrais faire une fonction dédiée à cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int concat(char **ppDynamicStr, char const *str)
    {
    	size_t totalLength = strlen(*ppDynamicStr) + strlen(str);
    	size_t totalSize = totalLength + 1;
    	char *pNew = realloc(*ppDynamicStr, totalSize);
    	if(pNew == NULL)
    		return -1;
     
    	*ppDynamicStr = pNew;
    	strcat(pNew, str);
    	return 0;
    }
    Bonne idée on peut également écrire une fonction de concaténation dynamique a multi-argument exemple de mon code ci-dessous, dont les remarques sont les bienvenus
    à bientôt
    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
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdarg.h>
     
    /***
    * Concaténation dynamique selon le nombre d'arguments
    * en fixant une taille suffisante préalablement et le dernier argument doit être NULL
    ***/
    char *f_Strcat( const size_t size, ... ){
     
    	va_list list;
    	size_t save_t = 0;
    	char *ptr = NULL;
    	char *pcy = NULL;
     
    	if( (size <= 0) )
    		return( ptr );
     
    	ptr = (char*)calloc( (size)+1, sizeof(char) );
    	if( ptr == NULL ){
    		perror("Erreur Allocation mémoire\n" );
    		exit( EXIT_FAILURE );
    	}
     
    	va_start( list, size );
    	while(  (pcy = va_arg(list,char*)) != NULL ){
     
    		save_t += strlen( pcy );
    		if( save_t < size+1 ){
    			if( strcat( ptr, pcy ) == NULL ){
    				free( ptr );
    				ptr = NULL;
    				fprintf( stderr,"Erreur de concaténation\n");
    				exit( EXIT_FAILURE );
    			}
    		}else{
    			free( ptr );
    			ptr = NULL;
    			fprintf( stderr,"Erreur taille mémoire\n");
    			exit( EXIT_FAILURE );
    		}
    	}
    	va_end(list);
    	return( ptr );
    }
     
    int main( void ){
     
     
    	char *ptr = NULL;
    	ptr = f_Strcat( 41, "Bonjour", " Joh la tringlette"
    			, " alias le baron", NULL);
    	if( ptr == NULL ){
    		fprintf( stderr,"Échec de la concaténation");
    		exit( EXIT_FAILURE );
    	}
     
    	printf("%s\n", ptr );
    	free( ptr );
    	ptr = NULL;
    	return( EXIT_SUCCESS );
    }
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  20. #20
    Membre confirmé
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Mars 2014
    Messages
    158
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur sécurité

    Informations forums :
    Inscription : Mars 2014
    Messages : 158
    Points : 465
    Points
    465
    Par défaut
    c’était une erreur de ma part je croyais qu'il falais faire -1 et non +1.
    je croyais que strlen comptait \0 aussi

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

Discussions similaires

  1. Réponses: 11
    Dernier message: 05/04/2009, 11h31
  2. Valeur BCD non correcte
    Par JP.NUAGE dans le forum Bases de données
    Réponses: 1
    Dernier message: 28/11/2008, 11h26
  3. Affichage info-bulle non correct suivant le navigateur
    Par [ced] dans le forum Mise en page CSS
    Réponses: 9
    Dernier message: 18/06/2008, 09h38
  4. Affichage non correct d'une image
    Par AnonCoder dans le forum Langage
    Réponses: 2
    Dernier message: 03/11/2006, 13h51
  5. Variables javascript non correctement définies
    Par LLaurent dans le forum XMLRAD
    Réponses: 5
    Dernier message: 11/05/2004, 12h39

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