CS50模糊滤镜上的UndefinedBehaviorSanitizer

时间:2020-07-21 14:21:29

标签: c undefined-behavior cs50

我似乎无法弄清楚为什么这个错误不断发生。我对编码还很陌生,该程序应该使用盒模糊对图像进行模糊处理,但是在尝试执行该程序时出现错误。我知道这可能不是最有效的解决方案,但是任何有关如何使它工作的提示都将不胜感激!

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE old[height][width];

    for(int i = 0; i < height; i++)
    {
        for(int j = 0; j < width; j++)
        {
            old[i][j] = image[i][j];
        }
    } 
    for(int i = 0; i < height; i++)
    {
        for(int j = 0; j < width; j++)
        {
            //top left corner
            if(j == 0 && i == 0)
            {
                image[i][j].rgbtRed = round( (old[i][j].rgbtRed + old[i][j+1].rgbtRed + old[i+1][j].rgbtRed + old[i+1][j+1].rgbtRed) /4);
                image[i][j].rgbtGreen = round( (old[i][j].rgbtGreen + old[i][j+1].rgbtGreen + old[i+1][j].rgbtGreen + old[i+1][j+1].rgbtGreen) /4);
                image[i][j].rgbtBlue = round( (old[i][j].rgbtBlue + old[i][j+1].rgbtBlue + old[i+1][j].rgbtBlue + old[i+1][j+1].rgbtBlue) /4);
            } 
            //top right corner
            else if(j == width && i == 0)
            {
                image[i][j].rgbtRed = round( (old[i][j].rgbtRed + old[i][j-1].rgbtRed + old[i+1][j].rgbtRed + old[i+1][j-1].rgbtRed) /4);
                image[i][j].rgbtGreen = round( (old[i][j].rgbtGreen + old[i][j-1].rgbtGreen + old[i+1][j].rgbtGreen + old[i+1][j-1].rgbtGreen) /4);
                image[i][j].rgbtBlue = round( (old[i][j].rgbtBlue + old[i][j-1].rgbtBlue + old[i+1][j].rgbtBlue + old[i+1][j-1].rgbtBlue) /4);
            } 
            //bottom left corner
            else if(j == 0 && i == height - 1)
            {
                image[i][j].rgbtRed = round( (old[i][j].rgbtRed + old[i][j+1].rgbtRed + old[i-1][j].rgbtRed + old[i-1][j+1].rgbtRed) /4);
                image[i][j].rgbtGreen = round( (old[i][j].rgbtGreen + old[i][j+1].rgbtGreen + old[i-1][j].rgbtGreen + old[i-1][j+1].rgbtGreen) /4);
                image[i][j].rgbtBlue = round( (old[i][j].rgbtBlue + old[i][j+1].rgbtBlue + old[i-1][j].rgbtBlue + old[i-1][j+1].rgbtBlue) /4);
            } 
            //bottom right corner
            else if(j == width && i == height - 1)
            {
                image[i][j].rgbtRed = round( (old[i][j].rgbtRed + old[i][j-1].rgbtRed + old[i-1][j].rgbtRed + old[i-1][j-1].rgbtRed) /4);
                image[i][j].rgbtGreen = round( (old[i][j].rgbtGreen + old[i][j-1].rgbtGreen + old[i-1][j].rgbtGreen + old[i-1][j-1].rgbtGreen) /4);
                image[i][j].rgbtBlue = round( (old[i][j].rgbtBlue + old[i][j-1].rgbtBlue + old[i-1][j].rgbtBlue + old[i-1][j-1].rgbtBlue) /4);
            } 
            //first row
            else if(i == 0 && j > 0 && j < width - 1)
            {
                image[i][j].rgbtRed = round( (old[i][j].rgbtRed + old[i][j+1].rgbtRed + old[i+1][j].rgbtRed + old[i+1][j+1].rgbtRed + old[i][j-1].rgbtRed + old[i+1][j-1].rgbtRed) /6);
                image[i][j].rgbtGreen = round( (old[i][j].rgbtGreen + old[i][j+1].rgbtGreen + old[i+1][j].rgbtGreen + old[i+1][j+1].rgbtGreen + old[i][j-1].rgbtGreen + old[i+1][j-1].rgbtGreen) /6);
                image[i][j].rgbtBlue = round( (old[i][j].rgbtBlue + old[i][j+1].rgbtBlue + old[i+1][j].rgbtBlue + old[i+1][j+1].rgbtBlue + old[i][j-1].rgbtBlue + old[i+1][j-1].rgbtBlue) /6);
            }
            //last row
            else if(i == height && j > 0 && j < width - 1)
            {
                image[i][j].rgbtRed = round( (old[i][j].rgbtRed + old[i][j+1].rgbtRed + old[i-1][j].rgbtRed + old[i-1][j+1].rgbtRed + old[i][j-1].rgbtRed + old[i-1][j-1].rgbtRed) /6);
                image[i][j].rgbtGreen = round( (old[i][j].rgbtGreen + old[i][j+1].rgbtGreen + old[i-1][j].rgbtGreen + old[i-1][j+1].rgbtGreen + old[i][j-1].rgbtGreen + old[i-1][j-1].rgbtGreen) /6);
                image[i][j].rgbtBlue = round( (old[i][j].rgbtBlue + old[i][j+1].rgbtBlue + old[i-1][j].rgbtBlue + old[i-1][j+1].rgbtBlue + old[i][j-1].rgbtBlue + old[i-1][j-1].rgbtBlue) /6);
            }
            //first column 
            else if(j == 0 && i > 0 && i < height - 1)
            {
                image[i][j].rgbtRed = round( (old[i][j].rgbtRed + old[i][j+1].rgbtRed + old[i+1][j].rgbtRed + old[i+1][j+1].rgbtRed + old[i-1][j].rgbtRed + old[i-1][j+1].rgbtRed) /6);
                image[i][j].rgbtGreen = round( (old[i][j].rgbtGreen + old[i][j+1].rgbtGreen + old[i+1][j].rgbtGreen + old[i+1][j+1].rgbtGreen + old[i-1][j].rgbtGreen + old[i-1][j+1].rgbtGreen) /6);
                image[i][j].rgbtBlue = round( (old[i][j].rgbtBlue + old[i][j+1].rgbtBlue + old[i+1][j].rgbtBlue + old[i+1][j+1].rgbtBlue + old[i-1][j].rgbtBlue + old[i-1][j+1].rgbtBlue) /6);
            }
            //last column
            else if(j == width && i > 0 && i < height - 1)
            {
                image[i][j].rgbtRed = round( (old[i][j].rgbtRed + old[i][j-1].rgbtRed + old[i+1][j].rgbtRed + old[i+1][j-1].rgbtRed + old[i-1][j].rgbtRed + old[i-1][j-1].rgbtRed) /6);
                image[i][j].rgbtGreen = round( (old[i][j].rgbtGreen + old[i][j-1].rgbtGreen + old[i+1][j].rgbtGreen + old[i+1][j-1].rgbtGreen + old[i-1][j].rgbtGreen + old[i-1][j-1].rgbtGreen) /6);
                image[i][j].rgbtBlue = round( (old[i][j].rgbtBlue + old[i][j-1].rgbtBlue + old[i+1][j].rgbtBlue + old[i+1][j-1].rgbtBlue + old[i-1][j].rgbtBlue + old[i-1][j-1].rgbtBlue) /6);
            }
            else if(i < height - 1 && j < width - 1)
            {
                image[i][j].rgbtRed = round( (old[i][j].rgbtRed + old[i][j+1].rgbtRed + old[i+1][j].rgbtRed + old[i+1][j+1].rgbtRed + old[i][j-1].rgbtRed + old[i+1][j-1].rgbtRed + old[i-1][j].rgbtRed + old[i-1][j-1].rgbtRed + old[j-1][i+1].rgbtRed) /9);
                image[i][j].rgbtGreen = round( (old[i][j].rgbtGreen + old[i][j+1].rgbtGreen + old[i+1][j].rgbtGreen + old[i+1][j+1].rgbtGreen + old[i][j-1].rgbtGreen + old[i+1][j-1].rgbtGreen + old[i-1][j].rgbtGreen + old[i-1][j-1].rgbtGreen + old[j-1][i+1].rgbtGreen) /9);
                image[i][j].rgbtBlue = round( (old[i][j].rgbtBlue + old[i][j+1].rgbtBlue + old[i+1][j].rgbtBlue + old[i+1][j+1].rgbtBlue + old[i][j-1].rgbtBlue + old[i+1][j-1].rgbtBlue + old[i-1][j].rgbtBlue + old[i-1][j-1].rgbtBlue + old[j-1][i+1].rgbtBlue) /9);
            }
        }
    }
}
UndefinedBehaviorSanitizer:DEADLYSIGNAL
==9889==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x7fff298bd0b8 (pc 0x000000442a96 bp 0x7fff298bc2b0 sp 0x7fff298071c0 T9889)
==9889==The signal is caused by a READ memory access.
    #0 0x442a95  (/home/ubuntu/pset4/filter/filter+0x442a95)
    #1 0x4232f1  (/home/ubuntu/pset4/filter/filter+0x4232f1)
    #2 0x7f302ce5db96  (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #3 0x402e19  (/home/ubuntu/pset4/filter/filter+0x402e19)

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

3 个答案:

答案 0 :(得分:0)

当您尝试对许多极端情况进行硬编码(字面意思是heh)时,可能会出现问题。为什么不尝试矩阵遍历呢?即构造一个虚构的矩阵,以当前像素([i][j])为中心,现在遍历该矩阵的所有 valid 像素并将其相加。简单高效。

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{

    RGBTRIPLE old[height][width];
    for (int i = 0; i < height; i++)
    {
        // Copy the original image over to a temporary variable, row by row
        memcpy(old[i], image[i], sizeof(RGBTRIPLE) * width);
    }
    // Iterate through rows
    for (int i = 0; i < height; i++)
    {
        // Iterate through columns
        for (int j = 0, red, green, blue, count; j < width; j++)
        {
            // Reset the variables
            red = blue = green = count = 0;
            // Move row-wise in the imaginary matrix (centered around [i][j])
            for (int r = i - 1; r <= i + 1; r++)
            {
                // Move column-wise in the imaginary matrix (centered around [i][j])
                for (int c = j - 1; c <= j + 1; c++)
                {
                    // Check for invalid pixels
                    if (r < 0 || r > height - 1)
                    {
                        // Invalid row, no need to continue, move on to next row
                        break;
                    }
                    if (c > -1 && c < width)
                    {
                        // Valid pixel
                        count++;
                        // Sum up every pixel color
                        red += old[r][c].rgbtRed;
                        green += old[r][c].rgbtGreen;
                        blue += old[r][c].rgbtBlue;
                    }
                }
            }
            // Calculate the average and assign
            image[i][j].rgbtRed = round((float)red / count);
            image[i][j].rgbtGreen = round((float)green / count);
            image[i][j].rgbtBlue = round((float)blue / count);
        }
    }
    return;
}

除了通过在每个像素周围构建一个虚构的矩阵并检查该矩阵的内部索引之外,此功能与您实现 所需的功能相同-问题要简单得多。

答案 1 :(得分:0)

“我似乎无法弄清楚为什么继续发生此错误。”
(关于异常信号:==9889==The signal is caused by a READ memory access.

尽管我同意其他答案中提供的建议,但它不能解决您所询问的核心问题,这很可能是由于代码中未定义的行为引起的。

注意:错误语句:signal is caused by a READ memory access.undefined behavior(UB)的症状,我的favorite definition类似于您所看到的。具体来说,您的代码在某些时候正试图写入它不拥有的内存。如果要写入的未拥有的内存碰巧被任何其他进程所拥有,那么您的程序甚至可能不会引发异常。但是,在您的情况下,您的进程不拥有 的内存很可能被另一个进程拥有,从而导致OS发出投诉并发出异常信号,表明您侵入了另一个人的属性(内存位置)。

有趣的是,您发布的代码没有明显的迹象表明分配正在尝试访问未拥有的内存。绑定所有分配的嵌套循环的条件:

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

显然不允许ij索引超出image数组的边界。 以及随后的语句,例如:

else if(j == width && i == 0)
for循环中的条件保证

永远不会允许j == width,从而防止尝试写到image[i][j].rgbtRed (如果{ {1}}将使数组超出一个内存位置。)并且是导致异常的原因。

因此,我建议由于未发布代码而可能发生异常。 (您从未在发生错误的确切位置的注释中回答问题。)您尚未找到它。无论您身在何处,找到根本原因并将其消除,这对您来说都是一个很好的举措。

或者,您可以发布minimal but complete, compilable example,从而使其他访问此帖子的人更好地帮助您找到它。

编辑 -我只用一个j == width函数(请参见下文)运行您的代码,但没有发现违反读取内存访问的证据在您发布的代码段中。我坚信在这一点上问题出在其他地方,也许在一段代码中您没有包括:

main()

答案 2 :(得分:0)

在例如j==width-1,对old[i][j+1]的访问将超出内部数组的末尾。尽管由丹尼斯·里奇(Dennis Ritchie)设计的C语言允许访问超出内部数组的范围,但最终在外部数组内,但是如果尝试进行此类访问,则Standard允许实现捕获或毫无意义地进行操作。我怀疑UndefinedbehaviorSanitizer正在标记此类访问。