2009-02-24 5 views
3

Je continue d'apprendre le langage C et j'ai commencé à l'utiliser pour générer des images. Je ne peux pas comprendre pourquoi un de mes programmes est segfaulting. Voici le code source, réduit à 40 lignes:L'ajout d'un membre int à une structure C provoque une erreur de segmentation

#include <stdio.h> 
#include <stdlib.h> 
struct color { 
     unsigned char r, g, b; 
}; 
struct image { 
     int w, h/*, o*/; 
     struct color **data; 
}; 
int main() { 
     // Declarations 
     int x, y; 
     struct color *black; 
     struct image *img; 
     // Set up color black 
     black = (struct color *) malloc(sizeof(struct color *)); 
     black->r = 0; 
     black->g = 0; 
     black->b = 0; 
     // Set up image img 
     img = (struct image *) malloc(sizeof(struct image *)); 
     img->w = 1; 
     img->h = 1; 
     /*img->o = 0;*/ 
     img->data = (struct color **) malloc(img->h * sizeof(struct color *)); 
     for (y = 0; y < img->h; y++) { 
       img->data[y] = (struct color *) malloc(img->w * sizeof(struct color)); 
     } 
     // Fill in img with black 
     for (x = 0; x < img->w; x++) { 
       for (y = 0; y < img->h; y++) { 
         img->data[y][x].r = black->r; 
         img->data[y][x].g = black->g; 
         img->data[y][x].b = black->b; 
       } 
     } 
     // Free black 
     free(black); 
     // Free img 
     for (y = 0; y < img->h; y++) 
       free(img->data[y]); 
     free(img->data); // Segfaults 
     free(img); // Also segfaults 
     return 0; 
} 

Il compile et fonctionne très bien (en utilisant gcc sur Ubuntu et Vista avec Cygwin), mais décommentant les deux lignes traitant img- > o le casse. J'ai le sentiment que c'est lié à this previous question, mais je suis en train de lancer tout ce qui doit être mallocé (je pense). Toute aide serait appréciée.

Répondre

21

Il y a un bogue dans vos instructions malloc. Vous utilisez un pointeur et non une structure. Cela vous donne seulement 4 octets de mémoire au lieu de la taille réelle requise par votre structure.

black = malloc(sizeof(*black)); 

Lors de l'allocation mémoire pour un pointeur, vous devez allouer de la mémoire pour la chose pointé du, pas le type du pointeur. Si vous écrivez simplement sizeof(*black) comme indiqué, vous obtiendrez toujours le bon type, même si le type de black change.

+1

de cette façon est également valide et plus claire, IMHO: noir = malloc (sizeof (struct noir)); – Tiago

1

À première vue, il semble que vous utilisiez un niveau supplémentaire d'indirection de pointeur, ce qui provoque le segfault. Lorsque vous mémoire malloc, il s'agit d'un pointeur sur l'objet, pas un pointeur sur un pointeur vers un objet. Donc, vous aurez:

img = (struct image *)malloc(sizeof(struct image)) 
img->o = 0 
+1

Vous n'avez pas besoin (et ne devez pas) convertir la valeur de retour de malloc() en C. – aib

0

Oups, le code a été coupé; J'ai oublié d'échapper à un signe inférieur. Ici, il est:

#include <stdio.h> 
#include <stdlib.h> 
struct color { 
    unsigned char r, g, b; 
}; 
struct image { 
    int w, h/*, o*/; 
    struct color **data; 
}; 
int main() { 
    // Declarations 
    int x, y; 
    struct color *black; 
    struct image *img; 
    // Set up color black 
    black = (struct color *) malloc(sizeof(struct color *)); 
    black->r = 0; 
    black->g = 0; 
    black->b = 0; 
    // Set up image img 
    img = (struct image *) malloc(sizeof(struct image *)); 
    img->w = 1; 
    img->h = 1; 
    /*img->o = 0;*/ 
    img->data = (struct color **) malloc(img->h * sizeof(struct color *)); 
    for (y = 0; y < img->h; y++) { 
     img->data[y] = (struct color *) malloc(img->w * sizeof(struct color)); 
    } 
    // Fill in img with black 
    for (x = 0; x < img->w; x++) { 
     for (y = 0; y < img->h; y++) { 
      img->data[y][x].r = black->r; 
      img->data[y][x].g = black->g; 
      img->data[y][x].b = black->b; 
     } 
    } 
    // Free black 
    free(black); 
    // Free img 
    for (y = 0; y < img->h; y++) 
     free(img->data[y]); 
    free(img->data); 
    free(img); 
    // Return 
    return 0; 
}
1

JaredPar a la bonne réponse, mais si vous obtenez une erreur de segmentation, la première chose à faire est de lancer le programme sous valgrind. C'est une aide énorme pour faire face à des problèmes comme celui-ci.

BTW, j'ai perdu des jours sur ce bug exact. Soyez heureux que vous l'ayez rencontré tôt dans votre carrière de programmeur en C et que vous fassiez toujours attention à cela dans le futur.

Questions connexes