3

私はまだCを学んでおり、それを使って画像を生成し始めました。私のプログラムの 1 つがセグメンテーション違反を起こしている理由がわかりません。ソースコードは次のとおりです。40行に短縮されています。

#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;
}

コンパイルして正常に実行されますが (Ubuntu では gcc を使用し、Cygwin を使用する Vista では)、img->o を扱う 2 行のコメントを外すと、問題が発生します。この前の質問に関連していると感じていますが、mallocする必要があるものはすべてmallocしています(と思います)。どんな助けでも大歓迎です。

4

4 に答える 4

21

malloc ステートメントにバグがあります。構造体ではなくポインターを malloc しています。これにより、構造体に必要な実際のサイズではなく、4 バイトのメモリしか得られません。

black = malloc(sizeof(*black));

ポインタにメモリを割り当てるときは、ポインタの型ではなく、指している対象にメモリを割り当てる必要があります。単純にこのように記述sizeof(*black)すれば、型が変わっても常に正しい型が得られblackます。

于 2009-02-24T02:04:50.723 に答える
1

一見すると、追加レベルのポインター間接化を使用しているように見え、それがセグメンテーション違反を引き起こしています。メモリを malloc すると、それはオブジェクトへのポインターではなく、オブジェクトへのポインターになります。したがって、次のようになります。

img = (struct image *)malloc(sizeof(struct image))
img->o = 0
于 2009-02-24T02:07:26.143 に答える
1

JaredPar は正しい答えを持っていますが、segfault が発生した場合は、最初に valgrind でプログラムを実行する必要があります。このような問題に対処するための大きな助けになります。

ところで、私はその正確なバグで何日も無駄にしました。C プログラミングのキャリアの早い段階でそれに遭遇したことを嬉しく思います。今後も常に気をつけてください。

于 2009-02-24T02:08:10.933 に答える
0

おっと、コードが途切れました。小なり記号をエスケープするのを忘れていました。ここにあります:

#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;
}
于 2009-02-24T02:07:32.277 に答える