与编译器优化结合的分段错误

segmentation fault in unions with compiler optimization

我的代码使用联合来表示 RGB 像素。它在调试模式下运行良好,但启用编译器优化后,它会出现段错误。

您可以在下面看到用于重现错误的简化测试代码。我的系统是 Ubuntu GCC4.8.2。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

union Pixel {
    uint32_t color;
    uint8_t at[4];
};

typedef struct Screen {
    union Pixel *pixels;
    int width;
    int height;
    int rPosition;
    int gPosition;
    int bPosition;
} *Screen;

Screen ScreenCreate(int width, int height, uint32_t rPosition, uint32_t gPosition, uint32_t bPosition) {
    Screen this = malloc(sizeof *this);
    this->pixels = malloc(width * height * sizeof this->pixels[0]);
    this->width = width;
    this->height = height;
    this->rPosition = rPosition;
    this->gPosition = gPosition;
    this->bPosition = bPosition;
}

void ScreenDelete(Screen this) {
    free(this->pixels);
    free(this);
}

void ScreenFill(Screen this, uint8_t r, uint8_t g, uint8_t b) {
    union Pixel pixel;
    pixel.color = 0;
    pixel.at[this->rPosition] = r;
    pixel.at[this->gPosition] = g;
    pixel.at[this->bPosition] = b;
    for (int i = 0; i < this->width * this->height; i += 1) {
        this->pixels[i].color = pixel.color;
    }
}

int main(void) {
    Screen screen = ScreenCreate(500, 500, 2, 1, 0);
    ScreenFill(screen, 0xff, 0xff, 0xff);
    ScreenDelete(screen);
    return 0;
}

在您的 ScreenCreate() 函数中,您忘记了一个 return 语句。因此,您的代码会产生未定义的行为。

最后一行应该是

 return this;

相关:根据 C11 标准,第 6.9.1 章,函数定义,第 12 段

If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.

所以,在 main() 中使用 screen 导致 undefined behaviour

故事的寓意:启用编译器警告并留意它们。