【问题标题】:Different writing, same thing: one gives segmentation fault, the other doesn't不同的写作,同样的事情:一个给出分段错误,另一个没有
【发布时间】:2021-06-15 19:01:44
【问题描述】:

有什么原因会导致分段错误:

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

typedef uint8_t  BYTE;

typedef struct
{
    BYTE  rgbtBlue;
    BYTE  rgbtGreen;
    BYTE  rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;

void edges(int height, int width, RGBTRIPLE image[height][width]) {
    RGBTRIPLE original[height][width];
            
    for(int i = 0; i < height; i++)
        for(int j = 0; j < width; j++)
            original[i][j] = image[i][j];
  
    for(int i = 0; i < height; i++)
        for(int j = 0; j < width; j++)
            for(int k = i - 1; k < i + 2; k++)
                for(int m = j - 1; m < j + 2; m++)
                    if(k < 0 || m < 0 || k == height || m == width) {
                        original[k][m].rgbtRed = 0;
                        original[k][m].rgbtGreen = 0;
                        original[k][m].rgbtBlue = 0;
                    }
}

与此相反?

if(k < 0 || m < 0 || k == height || m == width) {
   original[k][m].rgbtRed = original[k][m].rgbtGreen = original[k][m].rgbtBlue = 0;
}

这是唯一的区别,但前者会产生分段错误,而后者不会。

如果重要的话,我正在使用 CS50 IDE。

我无法给出完整的上下文,因为代码有数百行,但基本上这只是在 bmp 图像的每个像素上重复。这只发生在大图像上,而小图像既不返回段错误。

【问题讨论】:

  • 如果这些索引中的任何一个是&lt; 0,您就有未定义的行为。
  • 您正在使用or 这意味着,如果即k == -23 条件为真并且语句将被执行。这意味着original[-23][m]。这肯定不是你想要的。
  • 解决方法?不是真的:只是围绕访问越界元素的代码。或 (BIG BIG OR) 使您的数组大于所需的大小,以便您在顶部、底部、右侧、左侧有额外的元素......并且 still 避免写入越界!
  • 那么你应该展示一个完整的最小样本。
  • 发布minimal reproducible example 来拯救我们所有的时间。当然original[][] 被越界访问了。

标签: c if-statement segmentation-fault cs50


【解决方案1】:

在 C 语言中,禁止访问 [0, N-1] 范围之外的大小为 N 的数组。 在这两种情况下,您都在此范围之外访问,这就是您出现分段错误的原因。

【讨论】:

  • 但是为什么较小的图像或简单地改写函数不会触发分割错误?是因为它是未定义的行为吗?
  • 这是 UB。按预期工作是可能的结果。您想不惜一切代价避免使用 UB,否则您可能会认为您的代码是可以的,而实际上它只是在等待您的老板在您期望 y 时输入 Y ......并且在糟糕的时候呕吐:-)
  • 这不是被禁止的,但如果你这样做,程序会有未定义的行为,所以你不应该这样做。是的,未定义意味着未定义。
  • 如果代码在您重写之前就可以工作,这通常是未定义行为的良好指标(假设您在功能上等效地重写了它)。
  • 是的。这通常是一个很好的指标。例如:您执行printf("%d", val),它可以工作,然后您将其更改为printf("Value: %d", val),它突然停止工作。这种事。如果您看到这样的错误并且您可以确定更改是无关的,那么您的问题在您更改代码之前的其他地方。这就是 UB 的意思。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-01
  • 2021-07-16
  • 2015-12-14
  • 1970-01-01
相关资源
最近更新 更多