You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CS50 Pset4 filter-more 任务blur()函数输出异常问题排查

BMP图像3x3盒模糊功能输出异常排查

问题背景

  • 对应练习:CS50x 2022课程pset4 filter(more难度)板块
  • 实现逻辑:遍历图像每个像素,计算其周边3x3邻域内所有有效像素的RGB通道平均值,作为该像素模糊后的新值,实现BMP图像的模糊效果
  • 故障表现:代码可正常编译,调试过程未发现显性报错,但输出图像无预期模糊效果,反而垂直重复3次黑白彩色相间的异常图案
  • 当前进展:已根据评论建议做过部分代码调整,仍未得到符合预期的输出

相关代码

blur主函数

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
    // Array for storing corresponding blur values of the pixels.
    RGBTRIPLE(*blur)[width] = calloc(height, width * sizeof(RGBTRIPLE));
    if (image == NULL)
    {
        printf("Not enough memory to store blur pixels.\n");
        return;
    }


    for (int row = 0; row < height; row++)
    {
        for (int col = 0; col < width; col++)
        {
            sum3x3(row, col, height, width, image, blur);
        }
    }

    for (int row = 0; row < height; row++)
    {
        for (int col = 0; col < width; col++)
        {
            image[row][col] = blur[row][col];
        }
    }


    free(blur);
    return;
}

sum3x3邻域计算子函数

void sum3x3(int row, int col, int height, int width, RGBTRIPLE matrix[row][col], RGBTRIPLE new_matrix[row][col] )
{
    float counter = 0;
    float blue = 0;
    float green = 0;
    float red = 0;

    for (int i = -1; i < 2; i++)
    {
        for (int j = -1; j < 2; j++)
        {
            // skip rows out of range.
            if ( (i + row) < 0 || (i + row >= height)) continue;
            // skip columns out of range.
            if ( (j + col) < 0 || (j + col >= width)) continue;
            // add to sum.

            counter ++;

            blue += matrix[i + row][j + col].rgbtBlue;
            green += matrix[i + row][j + col].rgbtGreen;
            red += matrix[i + row][j + col].rgbtRed;

        }
    }

    new_matrix[row][col].rgbtBlue += round(blue/counter);
    new_matrix[row][col].rgbtGreen += round(green/counter);
    new_matrix[row][col].rgbtRed += round(red/counter);
}

RGBTRIPLE结构体定义

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

问题根因与修复方案

代码共有3处错误,其中第二处是导致输出异常图案的核心原因:

  1. 空指针判断逻辑写反:calloc申请的是blur数组的堆内存,判断内存申请是否失败时,错误检查了输入参数image是否为空,完全没有校验blur指针。如果内存不足申请失败,后续对blur的写入操作会直接触发内存访问错误。
    修复:将判断条件改为if (blur == NULL)。
  2. 变长数组形参维度定义错误:sum3x3函数的二维数组形参写为RGBTRIPLE matrix[row][col]、RGBTRIPLE new_matrix[row][col],这里第二维度误用了当前遍历的列号col,实际应为图像总宽度width,第一维度应为图像总高度height。C语言中访问二维数组时,会根据形参定义的第二维度计算每行的内存步长,维度写错会导致内存偏移计算完全错误,越界读取到非图像区域的垃圾值,最终输出重复的异常图案。
    修复:将两个二维数组形参改为RGBTRIPLE matrix[height][width]、RGBTRIPLE new_matrix[height][width]。
  3. 赋值逻辑冗余:calloc会将申请的内存全部初始化为0,此处用+=给通道赋值虽然不会出错,但逻辑上属于直接赋值场景,改用=可以避免后续更换内存分配方式(比如用malloc)时,因内存未初始化出现值累加的隐性bug。
    修复:将三个通道的+=改为=。

修复后的sum3x3函数核心代码:

void sum3x3(int row, int col, int height, int width, RGBTRIPLE matrix[height][width], RGBTRIPLE new_matrix[height][width] )
{
    float counter = 0;
    float blue = 0;
    float green = 0;
    float red = 0;

    for (int i = -1; i < 2; i++)
    {
        for (int j = -1; j < 2; j++)
        {
            if ( (i + row) < 0 || (i + row >= height)) continue;
            if ( (j + col) < 0 || (j + col >= width)) continue;
            counter ++;
            blue += matrix[i + row][j + col].rgbtBlue;
            green += matrix[i + row][j + col].rgbtGreen;
            red += matrix[i + row][j + col].rgbtRed;
        }
    }

    new_matrix[row][col].rgbtBlue = round(blue/counter);
    new_matrix[row][col].rgbtGreen = round(green/counter);
    new_matrix[row][col].rgbtRed = round(red/counter);
}

内容的提问来源于stack exchange,提问作者nishkant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 02:48:27