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 :

Stack smashing lors d'un free()


Sujet :

C

Vue hybride

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

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut Stack smashing lors d'un free()
    Salut,

    Je transforme un array en tableau deux dimensions, je peux ensuite remplir le tableau avec les données de l'array de base, manipuler les données et enregistrer le résultat dans un fichier sans problème.

    Toutefois lors de la libération du tableau apparaît ce problème et qui plante l'appli bien sur.
    Le tableau est créé comme ceci:
    Les données sont une image, on a donc width et height qui sont ses dimensions en pixels,
    chaque pixel est un uint32 pour les quatre composantes RGBA et buffer qui est l'array de base.
    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
     
        npixels = width * height;
        offset = npixels - width;
        length = 4 * width;
        uint32 *raster[height];
        for (row = 0; row < height; row++)
            raster[row] = malloc(width * sizeof(uint32));
     
        for (row = 0; row < height; row++) {
            memcpy(raster[row], buffer + offset, length);
            offset -= width;
        }
        _TIFFfree(buffer);
     
        // traitement des données du tableau .....
     
        for (row = 0; row < height; row++) {
            printf(" %lu", row);
            free(raster[row]);
        }
    Comme mon fichier image était correctement écrit, j'ai supposé que le problème venait de la fin du code, j'ai ajouté le printf(" %lu", row) pour vérifier ça.

    Je l'ai aussi testé sans aucune manipulation des données, donc du remplissage du tableau directement au free() avec le même résultat.

    Voici la sortie (abregée):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    0 1 2 ...... 2676 2677 2678 26*** stack smashing detected ***
    79 2680 2681 2682 2683 2684 2685 ....2864 2865 2866 2867Abandon (core dumped)
    Dans cet exemple, il s'agit d'une image de 2868 pixels de haut, le stack smashing apparaît toujours exactement au même endroit (row 2679) et pourtant il continue jusqu'au bout (row 2867).

    J'utilise gcc-4.5.3 sur Linux 64b.

  2. #2
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Tu rencontres probablement déjà un dépassement de capacité au premier memcpy : tu initialises length, pourtant tu ne te sers que de npixels et de width pour initialiser et décrémenter offset. Corrige déjà cet UB, on verra ensuite pour le dépassement de pile (possible qu'on ai besoin du reste du code).

    Pourquoi recopier ton image dans une série de buffers ? Tu ne veux pas utiliser un seul et unique bloc ? Ce serait bien plus simple et performant : malloc(npixels * 4) .

  3. #3
    Expert confirmé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Heu, il me semble que le troisième argument de memcpy est le nombre de bytes et pas le nombre de uint32 donc length = 4 * width.

    Me trompe-je ?

    La raison du changement du buffer est que celui-ci est rempli par la lib libtiff et que celle-ci se base sur le pixel inférieur gauche, donc buffer = row n,row n-1,row n-2, etc.
    Pour un filtre d'image (par ex contraste ou température de couleur) qui manipule des pixels seuls ça n'a pas d'importance mais pour un filtre dont l'algorithme procède avec les pixels voisins (ex non local means) cette disposition devient casse-tête, la disposition en tableau à l'identique de l'image facilite grandement les choses.

  4. #4
    Expert confirmé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par défaut
    Je réalise après coup ton interrogation, en fait le buffer est initialisé comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
        buffer = _TIFFmalloc(npixels * sizeof(uint32));
    après remplissage par libtiff on accède au pixels avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
            r = (int )TIFFGetR(buffer[p]);
            g = (int )TIFFGetG(buffer[p]);
            b = (int )TIFFGetB(buffer[p]);
            a = (int )TIFFGetA(buffer[p]);
    où p est l'index du pixel soit de 0 à npixels -1, c'est pourquoi offset est décrémenté de width et pas de width * 4

  5. #5
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    J'ai bien compris mais tu peux justement renverser l'ordre des lignes sans faire une allocation pour chacune.

    En ce qui concerne l'adressage, je reformule : la taille d'un élément (sizeof(uint32_t), ou 4) n'intervient pas dans ton calcul d'offset. Tu devrais :
    1. l'initialiser comme ceci : offset = (npixels - width) * 4; ;
    2. l'ajuster comme ceci : offset -= width * 4; (ou offset -= length;).


    EDIT : Ah, si buffer est de type uint32_t * (peu importe comment est réalisée l'allocation), alors effectivement c'est correct. C'est parcequ'il ne me viendrait pas à l'idée d'utiliser autre chose qu'un unsigned char *, déformation professionnelle.

Discussions similaires

  1. stack smashing detected lors d'une lecture de fichier
    Par Dave62 dans le forum Débuter
    Réponses: 5
    Dernier message: 06/11/2009, 13h50
  2. Problème de "stack smashing detected"
    Par Mr Light dans le forum C++
    Réponses: 9
    Dernier message: 29/02/2008, 09h09
  3. stack smashing detected et sscanf
    Par vinzzzz dans le forum Bibliothèque standard
    Réponses: 34
    Dernier message: 03/12/2007, 16h50
  4. "stack smashing detected" encore...
    Par incal dans le forum Débuter
    Réponses: 11
    Dernier message: 01/10/2007, 17h53
  5. plantage lors de mon free
    Par salseropom dans le forum C
    Réponses: 16
    Dernier message: 17/02/2006, 18h43

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