【问题标题】:Adding an int member to a C struct causes a segfault将 int 成员添加到 C 结构会导致段错误
【发布时间】:2010-10-09 11:21:51
【问题描述】:

我还在学习 C,并已开始使用它来生成图像。我不知道为什么我的一个程序会出现段错误。这是源代码,减少到 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 的两行会破坏它。我感觉它与this previous question 有关,但我正在对所有需要进行malloc 的东西进行malloc(我认为)。任何帮助将不胜感激。

【问题讨论】:

    标签: c struct malloc segmentation-fault


    【解决方案1】:

    您的 malloc 语句中存在错误。您正在分配指针而不是结构。这只会为您提供 4 字节的内存,而不是您的结构所需的实际大小。

    black = malloc(sizeof(*black));
    

    为指针分配内存时,需要为所指向的东西分配内存,不是指针的类型。如果你只写sizeof(*black),如图所示,即使black 的类型发生变化,你也总会得到正确的类型。

    【讨论】:

    • 这种方式也有效且更清晰,恕我直言:black = malloc(sizeof(struct black));
    【解决方案2】:

    乍一看,您似乎使用了额外级别的指针间接,这导致了段错误。当您 malloc 内存时,它是指向对象的指针,而不是指向对象指针的指针。所以你会有:

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

    【讨论】:

    • 你不需要(也不应该)在 C 中强制转换 malloc() 的返回值。
    【解决方案3】:

    糟糕,代码被截断了;我忘了逃避一个小于号。这里是:

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

    【讨论】:

      【解决方案4】:

      JaredPar 有正确的答案,但如果你遇到了段错误,首先要做的是在 valgrind 下运行程序。这对处理此类问题有很大帮助。

      顺便说一句,我在那个确切的错误上浪费了几天时间。很高兴您在 C 编程生涯的早期就遇到了它,并且将来会一直提防它。

      【讨论】:

        猜你喜欢
        • 2019-07-15
        • 1970-01-01
        • 2016-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-19
        • 1970-01-01
        相关资源
        最近更新 更多