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

实现Box Blur滤镜时触发Invalid read of size 1错误,求修复方案

修复方框模糊滤镜的段错误问题

我正在尝试为图像实现Box Blur(方框模糊)滤镜,核心逻辑是计算目标像素周围9个相邻像素的RGB平均值,再将新RGB值赋值给原像素。我创建了temp[][]像素数组,编写嵌套循环算法完成计算,但运行时出现段错误(Segmentation Fault)。使用Valgrind检测后得到以下结果:

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE temp[height][width];// creating temp array for blurred image

    //cycles for looping through the image
    for (int i=0; i < height; i++)
    {
        for (int j=0; j < width; j++)
        {
            int counter = 0; // amount of valid pixels
            float red = 0;
            float blue = 0;
            float green = 0;
            for (int k=i-1; k < i + 2; k++) // 3*3 square for adjacent pixels rows
            {
                if(i < 0 || i>= height ) // avoiding seg fault
                {
                    continue;
                }else
                {
                    for (int p=j-1; p < j+2; p++) // 3*3 square for adjacent pixels cols
                    {
                        if(j < 0 || j >= width ) // avoiding seg fault
                        {
                            continue;
                        }else
                        {// counting averages for 3*3 matrix
                            red += image[k][p].rgbtRed;
                            blue += image[k][p].rgbtBlue;
                            green += image[k][p].rgbtGreen;
                            counter++;
                        }
                    }
                }
            }
            // calculating averages
            red = round(red/counter);
            blue = round(blue/counter);
            green = round(green/counter);
            // assigning blurred values for temp array
            temp[i][j].rgbtRed = red;
            temp[i][j].rgbtBlue = blue;
            temp[i][j].rgbtGreen = green;
        }

    }

    for (int i=0; i < height; i++)
    {
        for (int j=0; j < width; j++)
        {
            image[i][j].rgbtRed   = temp[i][j].rgbtRed  ;
            image[i][j].rgbtBlue  = temp[i][j].rgbtBlue ;
            image[i][j].rgbtGreen = temp[i][j].rgbtGreen;
        }

    }
    return;
}

Valgrind检测输出:

filter-more/ $ valgrind ./filter -b images/yard.bmp OUTFILE.bmp
==28342== Memcheck, a memory error detector
==28342== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==28342== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==28342== Command: ./filter -b images/yard.bmp OUTFILE.bmp
==28342== 
==28342== Invalid read of size 1
==28342==    at 0x109B4A: blur (helpers.c:78)
==28342==    by 0x10953A: main (filter.c:105)
==28342==  Address 0x4b744bf is 1 bytes before a block of size 720,000 alloc'd
==28342==    at 0x484DA83: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==28342==    by 0x109425: main (filter.c:78)
==28342== 
==28342== Invalid read of size 1
==28342==    at 0x109B7C: blur (helpers.c:79)
==28342==    by 0x10953A: main (filter.c:105)
==28342==  Address 0x4b744bd is 3 bytes before a block of size 720,000 alloc'd
==28342==    at 0x484DA83: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==28342==    by 0x109425: main (filter.c:78)
==28342== 
==28342== Invalid read of size 1
==28342==    at 0x109BAD: blur (helpers.c:80)
==28342==    by 0x10953A: main (filter.c:105)
==28342==  Address 0x4b744be is 2 bytes before a block of size 720,000 alloc'd
==28342==    at 0x484DA83: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==28342==    by 0x109425: main (filter.c:78)
==28342== 
==28342== 
==28342== HEAP SUMMARY:
==28342==     in use at exit: 0 bytes in 0 blocks
==28342==   total heap usage: 5 allocs, 5 frees, 729,136 bytes allocated
==28342== 
==28342== All heap blocks were freed -- no leaks are possible
==28342== 
==28342== For lists of detected and suppressed errors, rerun with: -s
==28342== ERROR SUMMARY: 720000 errors from 3 contexts (suppressed: 0 from 0)

问题根源

你的边界判断完全错误:

  • 行越界判断用的是外层循环的i,但实际应该检查当前遍历的3x3区域行索引k
  • 列越界判断用的是外层循环的j,但实际应该检查当前遍历的3x3区域列索引p

i和j本身已经在0<=i<height、0<=j<width的合法范围内,所以这些判断永远不会触发。当处理图像边缘像素时,k会取到-1(比如i=0时)或height(比如i=height-1时),p会取到-1或width,直接访问了数组的非法内存区域,引发段错误。

修复后的代码

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE temp[height][width];// 创建存储模糊后图像的临时数组

    // 遍历图像每个像素
    for (int i=0; i < height; i++)
    {
        for (int j=0; j < width; j++)
        {
            int counter = 0; // 有效像素计数
            float red = 0;
            float blue = 0;
            float green = 0;
            // 遍历当前像素周围3x3区域的行
            for (int k=i-1; k < i + 2; k++)
            {
                // 检查行索引k是否越界
                if(k < 0 || k >= height )
                {
                    continue;
                }
                // 遍历当前像素周围3x3区域的列
                for (int p=j-1; p < j+2; p++)
                {
                    // 检查列索引p是否越界
                    if(p < 0 || p >= width )
                    {
                        continue;
                    }
                    // 累加RGB值
                    red += image[k][p].rgbtRed;
                    blue += image[k][p].rgbtBlue;
                    green += image[k][p].rgbtGreen;
                    counter++;
                }
            }
            // 计算平均值并取整
            red = round(red/counter);
            blue = round(blue/counter);
            green = round(green/counter);
            // 将模糊后的值存入临时数组
            temp[i][j].rgbtRed = red;
            temp[i][j].rgbtBlue = blue;
            temp[i][j].rgbtGreen = green;
        }

    }

    // 将临时数组的结果复制回原图像
    for (int i=0; i < height; i++)
    {
        for (int j=0; j < width; j++)
        {
            image[i][j].rgbtRed   = temp[i][j].rgbtRed  ;
            image[i][j].rgbtBlue  = temp[i][j].rgbtBlue ;
            image[i][j].rgbtGreen = temp[i][j].rgbtGreen;
        }

    }
    return;
}

额外优化建议

  • 去掉多余的else分支,continue已经会跳过后续代码,让逻辑更简洁
  • 如果处理大尺寸图像,栈上的temp数组可能导致栈溢出,建议改用malloc动态分配内存,使用完后记得调用free释放

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 11:50:34