CS50-PSet4(过滤器)-模糊

时间:2020-08-04 23:50:41

标签: c pointers cs50

我正在运行以下代码

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            int div = 1;

            if ( j + 1 < width - 1 && j + 1 > 0)
            {
                div++;
            }
            else
            {
                image[i][j + 1].rgbtRed = 0;
                image[i][j + 1].rgbtRed = 0;
                image[i][j + 1].rgbtRed = 0;
            }
             if ( i + 1 < height - 1 && i + 1 > 0)
            {
                div++;
            }
            else
            {
                image[i + 1][j].rgbtRed = 0;
                image[i + 1][j].rgbtRed = 0;
                image[i + 1][j].rgbtRed = 0;
            }
             if ( j + 1 < width - 1 && j + 1 > 0 && i + 1 < height - 1 && i + 1 > 0)
            {
                div++;
            }
            else
            {
                image[i + 1][j + 1].rgbtRed = 0;
                image[i + 1][j + 1].rgbtRed = 0;
                image[i + 1][j + 1].rgbtRed = 0;
            }
            if ( i - 1 < height - 1 && i - 1 > 0)
            {
                div++;
            }
            else
            {
                image[i - 1][j].rgbtRed = 0;
                image[i - 1][j].rgbtRed = 0;
                image[i - 1][j].rgbtRed = 0;
            }
            if ( i - 1 < height - 1 && i - 1 > 0 && j + 1 < width - 1 && j + 1 > 0)
            {
                div++;
            }
            else
            {
                image[i - 1][j + 1].rgbtRed = 0;
                image[i - 1][j + 1].rgbtRed = 0;
                image[i - 1][j + 1].rgbtRed = 0;
            }
             if ( j - 1 < width - 1 && j - 1 > 0)
            {
                div++;
            }
             else
            {
                image[i][j - 1].rgbtRed = 0;
                image[i][j - 1].rgbtRed = 0;
                image[i][j - 1].rgbtRed = 0;
            }
              if ( j - 1 < width - 1 && j - 1 > 0 && i + 1 < height - 1 && i + 1 > 0)
            {
                div++;
            }
            else
            {
                image[i + 1][j - 1].rgbtRed = 0;
                image[i + 1][j - 1].rgbtRed = 0;
                image[i + 1][j - 1].rgbtRed = 0;
            }
             if ( j - 1 < width - 1 && j - 1 > 0 && i - 1 < height - 1 && i - 1 > 0)
            {
                div++;
            }
            else
            {
                image[i - 1][j - 1].rgbtRed = 0;
                image[i - 1][j - 1].rgbtRed = 0;
                image[i - 1][j - 1].rgbtRed = 0;
            }
            int averageR = (float)(image[i][j].rgbtRed + image[i][j + 1].rgbtRed + image[i][j - 1].rgbtRed + image[i + 1][j].rgbtRed + image[i - 1][j].rgbtRed + image[i + 1][j + 1].rgbtRed + image[i + 1][j - 1].rgbtRed + image[i - 1][j + 1].rgbtRed + image[i + 1][j - 1].rgbtRed) / div;
            int averageG = (float)(image[i][j].rgbtGreen + image[i][j + 1].rgbtGreen + image[i][j - 1].rgbtGreen + image[i + 1][j].rgbtGreen + image[i - 1][j].rgbtGreen + image[i + 1][j + 1].rgbtGreen + image[i + 1][j - 1].rgbtGreen + image[i - 1][j + 1].rgbtGreen + image[i + 1][j - 1].rgbtGreen) / div;
            int averageB = (float)(image[i][j].rgbtBlue + image[i][j + 1].rgbtBlue + image[i][j - 1].rgbtBlue + image[i + 1][j].rgbtBlue + image[i - 1][j].rgbtBlue + image[i + 1][j + 1].rgbtBlue + image[i + 1][j - 1].rgbtBlue + image[i - 1][j + 1].rgbtBlue + image[i + 1][j - 1].rgbtBlue) / div;
        image[i][j].rgbtRed = round(averageR);
        image[i][j].rgbtGreen = round(averageG);
        image[i][j].rgbtBlue = round(averageB);
        }
    }
    return;
}

不幸的是,每次我尝试在模糊部分运行它时,都会显示以下消息:

UndefinedBehaviorSanitizer:DEADLYSIGNAL
==8771==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x7f7a4ec2890a (pc 0x000000427faa bp 0x7ffd07cd9170 sp 0x7ffd07cd7560 T8771)
==8771==The signal is caused by a WRITE memory access.
    #0 0x427fa9  (/home/ubuntu/pset4/filter/filter+0x427fa9)
    #1 0x4232b1  (/home/ubuntu/pset4/filter/filter+0x4232b1)
    #2 0x7f7a4db1bb96  (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #3 0x402dd9  (/home/ubuntu/pset4/filter/filter+0x402dd9)

UndefinedBehaviorSanitizer can not provide additional info.
==8771==ABORTING

知道这可能是什么吗?

1 个答案:

答案 0 :(得分:1)

您正在访问image二维数组的边界。

这发生在几个方面。

考虑循环:

for (int i = 0; i < height; i++)
{
    for (int j = 0; j < width; j++)
    {
        
    }
}

ij是可以分别从0和height以及0和width变化的索引。

但是对于这两个循环,您都可以访问此限制之外的内容。例如,如果j = width-1

if ( j + 1 < width - 1 && j + 1 > 0)
{
    div++;
}
else
{
    image[i][j + 1].rgbtRed = 0;
    image[i][j + 1].rgbtRed = 0;
    image[i][j + 1].rgbtRed = 0;
}

第一个条件不能为width-1+1 > width -1,因此您将进入else部分,您将在其中访问

image[i][width].rgbtRed = 0;

那是越界的!
每当i = height-1image[i + 1][j]之类的行将访问

image[height][j].rgbtRed = 0;

这也超出了范围。

超出范围访问数组会导致未定义的行为,这就是您的消毒器检测到的结果。


注意:尽管它与您要查找的错误无关,但您可能还想更正以下错误:

image[i][j + 1].rgbtRed = 0;
image[i][j + 1].rgbtRed = 0;
image[i][j + 1].rgbtRed = 0;

以及整个功能的类似部分。请注意,只有 Red 级别受到影响(三次!);我想您打算还影响 Green Blue


如何进行

为您实现整个功能将超出此问题的范围,但是我将尝试建议如何进行操作。

对于每个像素,您当前

  1. 计算不在图像边缘(div++)边缘的元素
  2. 将不应该影响平均值的元素设置为0(实际上是超出范围并导致您未定义的行为)
  3. 求和所有像素周围元素的所有值(包括设置为0的元素),然后除以div

但是,是什么迫使您对所有元素进行求和?仅对实际上有用的元素求和!您已经有一个执行此总和的正确位置:这是您递增div的位置。

类似的东西:

for (int i = 0; i < height; i++)
{
    for (int j = 0; j < width; j++)
    {
        int div = 1;
        int curRedSum = 0, curGReenSum = 0, curBlueSum = 0;

        if ( j + 1 < width - 1 && j + 1 > 0)
        {
            div++;
            curRedSum   += image[i][j + 1].rgbtRed;
            curGreenSum += image[i][j + 1].rgbtGreen;
            curBlueSum  += image[i][j + 1].rgbtBlue;
        }

        if ( i + 1 < height - 1 && i + 1 > 0)
        {
            div++;
            curRedSum   += image[i+1][j].rgbtRed;
            curGreenSum += image[i+1][j].rgbtGreen;
            curBlueSum  += image[i+1][j].rgbtBlue;
        }
        /* ... */
        float averageR = (float)(curRedSum / ( float )div );
        float averageG = (float)(curGreenSum / ( float )div );
        float averageB = (float)(curBlueSum / ( float )div );

        image[i][j].rgbtRed = round(averageR);   // Shouldn't this assignemnt be performed on a copy of the image?
        image[i][j].rgbtGreen = round(averageG); // Shouldn't this assignemnt be performed on a copy of the image?
        image[i][j].rgbtBlue = round(averageB);  // Shouldn't this assignemnt be performed on a copy of the image?
    }
}

免责声明:该建议仅是一个提示。我不保证无需任何进一步调整即可编译和运行。