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 :

[MALLOC] erreur de segmentation incomprise


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2005
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 65
    Par défaut [MALLOC] erreur de segmentation incomprise
    Bonsoir tout le monde

    Cela fait 1h que je tourne autour du pot.
    J'ai un programme à faire qui copie des BMP en le lisant entièrement, octet par octet, et qui l'écris dans un nouveau fichier.

    J'ai une fonction allouer_pixel qui alloue de la mémoire pour copier les octets de l'image.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    unsigned char* allouer_pixels(entete_bmp *entete){
        unsigned char * tab;
        printf("taille des données image : %d \n", entete->bitmap.taille_donnees_image);
        tab = (unsigned char *)malloc(entete->bitmap.taille_donnees_image);
        printf("Allouement effectué");
        return tab;
    }
    Le premier printf me sert à vérifier que la taille est bonne (ce qui est le cas).
    Mais pas moyen d'allouer la mémoire (que ce soit avec ou sans cast).
    C'est assez énervant de bloquer sur un truc pareil >.<
    Je suis sûr que c'est une erreur vraiment bète en plus =/

    Merci d'avance

  2. #2
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 082
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 082
    Par défaut
    Je pense qu'il serait de bon ton de verifier le pointeur et d'afficher un message d'erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    unsigned char* allouer_pixels(entete_bmp *entete)
    {
        unsigned char *tab = (unsigned char *)malloc(entete->bitmap.taille_donnees_image);
        if (tab == NULL)
            perror("Echec lors de l'appel a malloc dans la fonction allouer_pixels ");
        printf("Allouement effectué");
        return tab;
    }

    De maniere general, toujours verifié l'integrité de ses pointeurs.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2005
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 65
    Par défaut
    Le perror ne s'affiche même pas.
    J'ai essayé de mettre directement un int dans le malloc mais ca ne change rien.

  4. #4
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 082
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 082
    Par défaut
    Si le perror ne s'affiche pas, c'est que le malloc c'est bien passer. Je te conseille de regarder autre part.

    Sinon, post des morceaux de code pour qu'on puisse situer l'erreur, car c'est dur de te dire comme cela.

    Ah oui, entete->bitmap.taille_donnees_image doit etre de type unsigned char, une piste peut etre ? (mais ca m'etonnerai vu que le perror ne s'affiche pas)

  5. #5
    Membre Expert
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 962
    Par défaut
    Citation Envoyé par Link14 Voir le message
    Bonsoir tout le monde

    Cela fait 1h que je tourne autour du pot.
    J'ai un programme à faire qui copie des BMP en le lisant entièrement, octet par octet, et qui l'écris dans un nouveau fichier.

    J'ai une fonction allouer_pixel qui alloue de la mémoire pour copier les octets de l'image.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    unsigned char* allouer_pixels(entete_bmp *entete){
        unsigned char * tab;
        printf("taille des données image : %d \n", entete->bitmap.taille_donnees_image);
        tab = (unsigned char *)malloc(entete->bitmap.taille_donnees_image);
        printf("Allouement effectué");
        return tab;
    }
    Le premier printf me sert à vérifier que la taille est bonne (ce qui est le cas).
    Mais pas moyen d'allouer la mémoire (que ce soit avec ou sans cast).
    C'est assez énervant de bloquer sur un truc pareil >.<
    Je suis sûr que c'est une erreur vraiment bète en plus =/

    Merci d'avance
    le fait de ne pas avoir mis de "\n" à la fin de "Allouement effectué" fait que stdout n'est pas flushé immédiatement…

  6. #6
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 082
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 082
    Par défaut
    Citation Envoyé par JeitEmgie Voir le message
    le fait de ne pas avoir mis de "\n" à la fin de "Allouement effectué" fait que stdout n'est pas flushé immédiatement…
    Honnetement, je ne pense pas que l'erreur vienne d'ici. Il met arrivé plusieurs fois de ne pas mettre '\n' a la fin d'un printf sans pour autant que cela bloque mon affichage.

    En fait, tout est trop vague. Existe t'il reelement une erreur ? Ou bien est ce juste que le code fait bien ce qu'on lui demande mais que cela ne corresponde pas a l'attente du codeur ?

    S'il y a une erreur donné par le compilo, quelle est elle ?


    Bref, a suivre ...

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2005
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 65
    Par défaut
    C'était en effet le problème du \n Les printf ce s'affichaient pas...
    l'allocation marche en tout cas

    donc en fait c'est l'écriture qui ne passe pas (pourtant je pensais avoir essayé de voir si c'était le malloc qui ne passait pas ou l'écriture ).

    voilà maintenant le petit rebelle :
    la lecture des 54 premiers octetcs ne m'intéressent pas, j'ai donc mis çà "à la poubelle" parce que je ne savais pas comment m'en débarasser.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    int lire_pixels(int de, entete_bmp *entete, unsigned char *pixels){
        char poubelle;
        read(de, &poubelle, 54);
        printf("étape lirepixel \n");
        return read(de, pixels, entete->bitmap.taille_donnees_image);
    }
    en sachant que mon allocation a été faite avec cette autre fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    int copier_bmp(int de, int vers){
        entete_bmp entete;
        unsigned char *pixels;
     
        /*lecture du fichier source*/
        lire_entete(de, &entete);
        pixels = allouer_pixels(&entete);
        printf("Allouement effectué \n");
        lire_pixels(de, &entete, pixels);
        printf("Lire pixel OK \n");
     
        /*écriture du fichier destination*/
        ecrire_entete(vers, &entete);
        ecrire_pixels(vers, &entete, pixels);
     
        /*on libère les pixels*/
        free(pixels);
        return 1;

  8. #8
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 082
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 082
    Par défaut
    Je ne comprend plus rien. Lors de ton premier post, tu disais avoir un probleme de malloc. C'est juste parce le printf ne s'affichait pas ??

    Maintenant tu dis, "voilà maintenant le petit rebelle :"

    Il y a un probleme avec cette fonction ?

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2005
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 65
    Par défaut
    Ah oui désolé de ne pas être assez précis.
    Au départ je pensais que c'était le malloc qui ne passait pas.
    J'avais essayé en mettant des printf avant et après, sauf que comme j'avais oublié ce fameux '\n' et bien le printf ne s'affichait pas. Donc du coup je pensais que le malloc ne fonctionnait pas.

    Maintenant j'ai pu faire des autres tests et c'est bien l'écriture qui ne fonctionne pas :
    read(de, pixels, entete->bitmap.taille_donnees_image);

  10. #10
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 082
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 082
    Par défaut
    ^^

    L'ecriture ne fonctionne pas ?

    C'est a dire ? Je ne suis pas calé avec read, donc tout indice peut etre bon a prendre.

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2005
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 65
    Par défaut
    Alors le read lit le fichier correspondant au descripteur de, lis les "entete->bitmap.taille_donnees_image" octets et les places dans pixels, qui est alloué via la fonctions du premier post.

  12. #12
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 082
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 082
    Par défaut
    Bon, cela decrit juste ce que tu pense faire.
    Les fonctions provenant des librairie sont generalement bien codé : elle renvoie en general quelque chose :

    pour les fonctions renvoyant des pointeur : un pointeur en cas de reussite
    : NULL en cas d'echec

    pour les fonctions renvoyant des entienrd : un chiffre : reussite et resulta escompté
    : en general, 0 ou -1 -> erreur.


    Bref, tout ca pour te dire qu'en general, si une fonction se passe mal, elle renvoi un code d'erreur. read n'echappe pas a cette regle, et pour connaitre un minimum une fonction inconnu, rien ne vaut que de lire la page "man".

    ssize_t read(int fd, void *buffer, size_t n);

    Cette fonction lit n octets dans le fichier dont le descripteur est fd et les place dans un buffer. En cas de réussite, elle renvoie le nombre d'octets transferés, sinon elle retourne -1.
    Ceci n'est pas tiré du man, mais est assez explicite.


    Donc, si read echoue, elle renvoi -1.

    Pour en revenir a toi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if (read(de, pixels, entete->bitmap.taille_donnees_image) == -1)
        printf("Erreur !\n");

    Cependant, si tu as une erreur, ce serait cool de savoir pourquoi. Chique, il existe ceci :

    Nom
    perror - Affiche un message d'erreur.
    Synopsis
    #include <stdio.h>

    void perror (const char *s);

    #include <errno.h>

    const char *sys_errlist[];
    int sys_nerr;
    Description
    La fonction perror() affiche un message sur la sortie d'erreur standard, décrivant la dernière erreur rencontrée durant un appel système ou une fonction de bibliothèque. La chaîne de caractère s est imprimée en premier, suivie d'un double-point ou d'un blanc, puis le message, suivi d'un saut de ligne.

    Donc,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    if (read(de, pixels, entete->bitmap.taille_donnees_image) == -1)
    {
        perror("Probleme lors d'un read avec comme argument : de, pixels, entete->bitmap.taille_donnees_image ");
        printf("Erreur");
    }
    Voila, a moins que perror ne gere pas read, tu as de quoi verifier si read marche ou non, et si read ne marche pas, pourquoi.

  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2005
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 65
    Par défaut
    Merci pour cette réponse on ne peut plus complète !
    C'est vrai que je pense rarement à utiliser les messages d'erreur

    J'ai vu que la taille de lecture ne passait pas déjà (en en mettant une au pif, comme 100000, le read se faisait mais il me sortait un "bad file descriptor").
    Je ne comprenais pas trop pourquoi.
    C'est là que j'ai décidé d'enlever le premier read (de 54 octets).
    Et donc du coup j'ai réussi à faire marcher tout çà!
    Le bmp se copie parfaitement bien !

    J'ai réarangé le tout, ce qui donne çà :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    int lire_pixels(int de, entete_bmp *entete, unsigned char *pixels){
        int n;
        printf("étape lirepixel \n");
        n = read(de, pixels, entete->bitmap.taille_donnees_image);
        if (n == -1){
            perror("Probleme lors d'un read avec comme argument : de, pixels, entete->bitmap.taille_donnees_image ");
        }
        return n;
    }

  14. #14
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 082
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 082
    Par défaut
    Je suis content d'avoir reussi a te sensibiliser a la gestion d'erreur.
    Une bonne habitude de prise ^^

    Pour ton message d'erreur : "bad file descriptor"

    Je dirais plutot que c'est le premier argument qui ne serai plus valide puisqu'il s'agit du descripteur de fichier.

    Bref, cela semble enfin marcher.
    Bonne continuation.

    EDIT : si tu veux mettre resolu, clique sur ton post et regarde apres le dernier message, il y a le bouton tout simplement.

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

Discussions similaires

  1. Erreur de segmentation sur malloc
    Par kolodz dans le forum Débuter
    Réponses: 4
    Dernier message: 26/03/2015, 09h06
  2. Erreur de segmentation GTK2.0 incomprise
    Par baguiwoopy dans le forum GTK+ avec C & C++
    Réponses: 3
    Dernier message: 24/04/2012, 20h36
  3. Erreur de segmentation GTK2.0 incomprise
    Par baguiwoopy dans le forum C
    Réponses: 2
    Dernier message: 24/04/2012, 19h44
  4. [GMP] Erreur de segmentation incomprise
    Par SeaX dans le forum C
    Réponses: 0
    Dernier message: 21/02/2008, 14h55
  5. erreur de segmentation
    Par transistor49 dans le forum C++
    Réponses: 10
    Dernier message: 15/03/2005, 11h18

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