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

Bibliothèque standard C Discussion :

free provoquant une erreur


Sujet :

Bibliothèque standard C

  1. #1
    Membre expérimenté
    Avatar de GLDavid
    Homme Profil pro
    Head of Service Delivery
    Inscrit en
    Janvier 2003
    Messages
    2 896
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Head of Service Delivery
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 2 896
    Par défaut free provoquant une erreur
    Bonjour

    Voici mon problème. Je développe avec gcc v4.1.2 sous CentOS.
    J'écris la fonction suivante:
    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 writeLog(char *message){
        int length = 23;
        char outstr[length];
        time_t t;
        struct tm *tmp;
        char* out;
        FILE *log = fopen(logfile, "a+");
     
        out = (char *)malloc(sizeof(char)*(strlen(outstr)+strlen(message)));
        checkPointer(out, "Null pointer", 6);
        t = time(NULL);
        tmp = localtime(&t);
        checkPointer(tmp, "Can not initialise time", 7);
        if (strftime(outstr, sizeof (outstr), "%Y-%m-%d %X   ", tmp) == 0) {
            raise_error("Unable to set time", 8);
        }
        out = strcat(outstr, message);
        checkPointer(out, "Null pointer", 6);
        fprintf(log, "%s\n", out);
        fflush(log);
        fclose(log);
    }
    Evidemment, je veux écrire un fichier log. Par contre, si j'ajoute à la fin de ma fonction un free(out), mon programme échoue à cette ligne avec la sortie suivante:
    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
     
    *** glibc detected *** /home/dbourgais/Projects/Streptomics/GenomeAssembling/mpa/dist/make_pairwise_alignment: double free or corruption (out): 0xbfbf4810 ***
    ======= Backtrace: =========
    /lib/libc.so.6[0xa440f1]
    /lib/libc.so.6(cfree+0x90)[0xa47bc0]
    /home/dbourgais/Projects/Streptomics/GenomeAssembling/mpa/dist/make_pairwise_alignment[0x80488c7]
    /home/dbourgais/Projects/Streptomics/GenomeAssembling/mpa/dist/make_pairwise_alignment[0x804898f]
    /home/dbourgais/Projects/Streptomics/GenomeAssembling/mpa/dist/make_pairwise_alignment[0x80489bc]
    /lib/libc.so.6(__libc_start_main+0xdc)[0x9f0e8c]
    /home/dbourgais/Projects/Streptomics/GenomeAssembling/mpa/dist/make_pairwise_alignment[0x8048591]
    ======= Memory map: ========
    001a1000-001ac000 r-xp 00000000 fd:04 3178735    /lib/libgcc_s-4.1.2-20080825.so.1
    001ac000-001ad000 rwxp 0000a000 fd:04 3178735    /lib/libgcc_s-4.1.2-20080825.so.1
    00873000-0087a000 r-xp 00000000 fd:04 3179312    /lib/librt-2.5.so
    0087a000-0087b000 r-xp 00006000 fd:04 3179312    /lib/librt-2.5.so
    0087b000-0087c000 rwxp 00007000 fd:04 3179312    /lib/librt-2.5.so
    009bd000-009d7000 r-xp 00000000 fd:04 3178685    /lib/ld-2.5.so
    009d7000-009d8000 r-xp 00019000 fd:04 3178685    /lib/ld-2.5.so
    009d8000-009d9000 rwxp 0001a000 fd:04 3178685    /lib/ld-2.5.so
    009db000-00b19000 r-xp 00000000 fd:04 3178711    /lib/libc-2.5.so
    00b19000-00b1b000 r-xp 0013e000 fd:04 3178711    /lib/libc-2.5.so
    00b1b000-00b1c000 rwxp 00140000 fd:04 3178711    /lib/libc-2.5.so
    00b1c000-00b1f000 rwxp 00b1c000 00:00 0 
    00b4a000-00b4c000 r-xp 00000000 fd:04 3178729    /lib/libdl-2.5.so
    00b4c000-00b4d000 r-xp 00001000 fd:04 3178729    /lib/libdl-2.5.so
    00b4d000-00b4e000 rwxp 00002000 fd:04 3178729    /lib/libdl-2.5.so
    00b7b000-00b7c000 r-xp 00b7b000 00:00 0          [vdso]
    00c8f000-00ca2000 r-xp 00000000 fd:04 3179150    /lib/libpthread-2.5.so
    00ca2000-00ca3000 r-xp 00012000 fd:04 3179150    /lib/libpthread-2.5.so
    00ca3000-00ca4000 rwxp 00013000 fd:04 3179150    /lib/libpthread-2.5.so
    00ca4000-00ca6000 rwxp 00ca4000 00:00 0 
    00d21000-00d24000 r-xp 00000000 fd:04 42274988   /home/dbourgais/netbeans-6.7/dlight1/tools/Linux-x86/bin/prof_agent.so
    00d24000-00d25000 r-xp 00002000 fd:04 42274988   /home/dbourgais/netbeans-6.7/dlight1/tools/Linux-x86/bin/prof_agent.so
    00d25000-00d26000 rwxp 00003000 fd:04 42274988   /home/dbourgais/netbeans-6.7/dlight1/tools/Linux-x86/bin/prof_agent.so
    00f3d000-00f3e000 r-xp 00000000 fd:04 42274976   /home/dbourgais/netbeans-6.7/dlight1/bin/nativeexecution/Linux-x86/unbuffer.so
    00f3e000-00f3f000 rwxp 00000000 fd:04 42274976   /home/dbourgais/netbeans-6.7/dlight1/bin/nativeexecution/Linux-x86/unbuffer.so
    08048000-08049000 r-xp 00000000 fd:04 45581947   /home/dbourgais/Projects/Streptomics/GenomeAssembling/mpa/dist/make_pairwise_alignment
    08049000-0804a000 rw-p 00000000 fd:04 45581947   /home/dbourgais/Projects/Streptomics/GenomeAssembling/mpa/dist/make_pairwise_alignment
    08505000-08526000 rw-p 08505000 00:00 0          [heap]
    b7e00000-b7e21000 rw-p b7e00000 00:00 0 
    b7e21000-b7f00000 ---p b7e21000 00:00 0 
    b7f23000-b7f25000 rw-p b7f23000 00:00 0 
    b7f3e000-b7f3f000 rw-p b7f3e000 00:00 0 
    bfbe1000-bfbf6000 rw-p bffea000 00:00 0          [stack]
     
    RUN FAILED (exit value 134, total time: 592ms)
    Pourquoi un free provoquerait une telle erreur ?

    Merci d'avance de votre aide.

    @++
    GLDavid
    Consultez la FAQ Perl ainsi que mes cours de Perl.
    N'oubliez pas les balises code :tagcode: ni le tag :resolu:

    Je ne répond à aucune question technique par MP.

  2. #2
    Invité(e)
    Invité(e)
    Par défaut
    Bonjour,

    L'erreur à l'appel du free peut être du au fait que tu écrives plus que ce que tu as alloué :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        char outstr[length];
        out = (char *)malloc(sizeof(char)*(strlen(outstr)+strlen(message)));
    Dans l'allocation de out, du demande la taille de outstr, or outstr est dans un état indéterminé, donc strlen(outstr) peut retourner n'importe quoi.

    Une solution serait d'écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        out = (char *)malloc(sizeof(char)*(sizeof outstr + strlen(message) + 1));
    Le '+1' est là pour tenir compte du caractère \'0' final.

  3. #3
    Membre expérimenté
    Avatar de GLDavid
    Homme Profil pro
    Head of Service Delivery
    Inscrit en
    Janvier 2003
    Messages
    2 896
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Head of Service Delivery
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 2 896
    Par défaut
    Hello mabu

    Merci pour ce tuyau. Malheureusement, bien qu'utilisant ta ligne d'allocation, j'ai toujours le même résultat. Hélas, 3 fois halas.
    Merci encore pour ta réponse.

    @++
    GLDavid
    Consultez la FAQ Perl ainsi que mes cours de Perl.
    N'oubliez pas les balises code :tagcode: ni le tag :resolu:

    Je ne répond à aucune question technique par MP.

  4. #4
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    j'ajouterais qu'utiliser un comportement "object-like" avec des RaiseError et des trucs comme ça (à moins que dans cette fonction il y ait un exit) est hautement dangereux, car normalement en C le programme continue...


    A part pour des fonction qui contiendraient exit, le processus se déroule. Il n'y a pas de notions d'exceptions.. de try-catch.. etc..

    La gestion des erreurs est à inclure dans le flot du programme...

  5. #5
    Membre expérimenté
    Avatar de GLDavid
    Homme Profil pro
    Head of Service Delivery
    Inscrit en
    Janvier 2003
    Messages
    2 896
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Head of Service Delivery
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 2 896
    Par défaut
    Hello souviron

    Il y a effectivement un exit dans ma fonction raise_error. la preuve:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    void warn(char *message){
        fprintf(stderr, "%s\n", message);
    }
     
    void raise_error(char *message, int exit_code){
        warn(message);
        exit(exit_code);
    }
    @++
    GLDavid
    Consultez la FAQ Perl ainsi que mes cours de Perl.
    N'oubliez pas les balises code :tagcode: ni le tag :resolu:

    Je ne répond à aucune question technique par MP.

  6. #6
    Invité(e)
    Invité(e)
    Par défaut
    Citation Envoyé par GLDavid Voir le message
    Hello mabu

    Merci pour ce tuyau. Malheureusement, bien qu'utilisant ta ligne d'allocation, j'ai toujours le même résultat. Hélas, 3 fois halas.
    Merci encore pour ta réponse.

    @++
    Je viens de me rendre compte que tu n'utilises pas strcat comme il faut :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    out = strcat(outstr, message);
    à remplacer par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    strcpy(out, outstr);
    strcat(out, message);
    Dans la première version du code, tu modifies la valeur de out, donc l'adresse donnée à free n'est plus celle allouée par malloc.

    EDIT : ou une méthode plus sure, c'est d'éviter d'utiliser des tableaux dynamiques :
    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
    void writeLog(char *message){
        char outstr[23];
        time_t t;
        struct tm *tmp;
        char* out;
        FILE *log = fopen(logfile, "a+");
     
        t = time(NULL);
        tmp = localtime(&t);
        checkPointer(tmp, "Can not initialise time", 7);
        if (strftime(outstr, sizeof (outstr), "%Y-%m-%d %X   ", tmp) == 0) {
            raise_error("Unable to set time", 8);
        }
        checkPointer(out, "Null pointer", 6);
        fprintf(log, "%s%S\n", outstr, message);
        fflush(log);
        fclose(log);
    }

  7. #7
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par GLDavid Voir le message
    Hello souviron

    Il y a effectivement un exit dans ma fonction raise_error. la preuve:
    ok, mais c'est quand même un comportement étrange...

    Un petit programme perso, ok..

    Un serveur qui ne peut obtenir de port, ok.

    Pour le reste, un programme professionnel, safe, etc, c'est violent et souvent inapproprié... Surtout pour une allocation défaillante...


    Note : de plus il n'y a pas de vérification que le fichier s'est correctement ouvert...

  8. #8
    Membre expérimenté
    Avatar de GLDavid
    Homme Profil pro
    Head of Service Delivery
    Inscrit en
    Janvier 2003
    Messages
    2 896
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Head of Service Delivery
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 2 896
    Par défaut
    Great mabu

    Je suis d'accord avec toi et ça tourne.
    Un grand merci pour ton aide.

    @++
    GLDavid
    Consultez la FAQ Perl ainsi que mes cours de Perl.
    N'oubliez pas les balises code :tagcode: ni le tag :resolu:

    Je ne répond à aucune question technique par MP.

  9. #9
    Membre expérimenté
    Avatar de GLDavid
    Homme Profil pro
    Head of Service Delivery
    Inscrit en
    Janvier 2003
    Messages
    2 896
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Head of Service Delivery
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 2 896
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    ok, mais c'est quand même un comportement étrange...

    Un petit programme perso, ok..

    Un serveur qui ne peut obtenir de port, ok.

    Pour le reste, un programme professionnel, safe, etc, c'est violent et souvent inapproprié... Surtout pour une allocation défaillante...


    Note : de plus il n'y a pas de vérification que le fichier s'est correctement ouvert...
    Hello Souviron

    Je suis d'accord avec tes remarques sauf que je m'inscris plus dans le cas d'une petite application qui doit faire une chose et une seule mais qui doit bien le faire. Si je la fais sortir ainsi, peut être suis-je trop prudent, mais au moins, je peux savoir pourquoi.

    Mais ton oeil attentionné à pointé une défaillance, la non-vérification de l'ouverture du fichier que je vais immédiatement pallier.
    Merci à toi.

    @++
    GLDavid
    Consultez la FAQ Perl ainsi que mes cours de Perl.
    N'oubliez pas les balises code :tagcode: ni le tag :resolu:

    Je ne répond à aucune question technique par MP.

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

Discussions similaires

  1. [Threads] Savoir si un thread a provoqué une erreur
    Par anykeyh dans le forum Windows
    Réponses: 6
    Dernier message: 26/04/2006, 15h12
  2. msaccess a provoqué une erreur dans KERNEL32.dll
    Par massol joel dans le forum Access
    Réponses: 12
    Dernier message: 03/04/2006, 14h32
  3. Cells (1,1) provoque une erreur
    Par Opo dans le forum Access
    Réponses: 9
    Dernier message: 07/03/2006, 16h29
  4. [SGBD] mysql_fetch_array provoque une erreur
    Par nicerico dans le forum Requêtes
    Réponses: 6
    Dernier message: 06/10/2005, 14h20
  5. Select Case provoque une erreur
    Par defluc dans le forum SQL
    Réponses: 6
    Dernier message: 14/08/2005, 23h59

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