【问题标题】:segmentation fault in unions with compiler optimization编译器优化联合中的分段错误
【发布时间】:2015-06-24 03:25:28
【问题描述】:

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

您可以查看下面的简化测试代码来重现错误。我的系统是带有 GCC4.8.2 的 Ubuntu。

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

【问题讨论】:

  • 我不建议在 C 代码(尤其是头文件内部)中使用 C++ 关键字(如 this)。
  • typedef struct Screen *Screen;,这真的很混乱。最好不要使用指针类型定义;但如果必须,请给它们一个不同于它们指向的类型的名称。

标签: c segmentation-fault return


【解决方案1】:

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

最后一行应该是

 return this;

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

如果到达终止函数的},并且调用者使用了函数调用的值,则行为未定义。

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

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

【讨论】:

  • @xiver77 因为它调用了undefined behaviour
  • 而且我很确定,如果您确实使用gcc -Wall -Wextra 进行编译,编译器会警告您。
  • @xiver77 未定义的行为可能包括按预期工作。
猜你喜欢
  • 2013-10-07
  • 1970-01-01
  • 2014-05-10
  • 1970-01-01
  • 1970-01-01
  • 2016-12-09
  • 1970-01-01
  • 2015-08-12
  • 1970-01-01
相关资源
最近更新 更多