CS50 Blur报floating point exception(core dumped)错误排查
CS50 Filter-less 模糊功能报错修复
你代码里的问题直接导致运行崩溃和结果错误,核心问题点如下:
- 触发
floating point exception的根因是除零错误:你把边界判断写在了for循环的终止条件里,当处理第一行(i初始值为pxlheight-1 = -1)时,循环条件直接判定为不成立,外层for循环一次都不会执行,最终用来做除数的x*y值为0,自然触发除零崩溃。 - 像素计数逻辑错误:你分开统计有效行数y和有效列数x再相乘的思路本身就不成立,再加上循环提前终止的问题,根本统计不到正确的邻域像素总数。
- 结构体未初始化:你声明的
caca是栈上的局部变量,没有给它的rgbtRed/rgbtGreen/rgbtBlue赋初始值就直接做+=累加,这三个成员的初始值是内存里的随机垃圾值,哪怕循环正常跑,最终结果也是错的。 - 整数除法丢精度:你直接用int类型的颜色总和除以像素数,属于整数截断运算,哪怕外层套了
round()也没用——除法运算在传入round之前就已经丢失小数部分了,计算结果会有偏差。
修正思路
- 不要把边界判断写在for循环的条件表达式里,固定遍历邻域3x3共9个偏移量,在循环内部单独判断坐标是否落在图片合法范围内,合法才做累加和计数,不合法直接跳过,避免循环提前终止。
- 用单个计数器统计实际参与计算的邻域像素总数,不要分开算行列数再相乘。
- 声明临时存储颜色和的变量时初始化为0,不要直接用未初始化的结构体成员存累加值。
- 计算平均值时先把总和转为浮点数再做除法,最后用round取整后赋值给结构体成员。
修正后的可运行代码
// 模糊主函数 void blur(int height, int width, RGBTRIPLE image[height][width]) { // 原副本分配逻辑正确,无需修改 RGBTRIPLE (*copy)[width] = calloc(height, width * sizeof(RGBTRIPLE)); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { copy[i][j] = image[i][j]; } } for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { image[i][j] = average(i, j, height, width, copy); } } free(copy); return; } // 邻域平均值计算函数 RGBTRIPLE average(int pxlheight, int pxlwidth, int height, int width, RGBTRIPLE copy[height][width]) { RGBTRIPLE res; int sumRed = 0, sumGreen = 0, sumBlue = 0; int count = 0; // 固定遍历3x3邻域的9个坐标偏移 for (int di = -1; di <= 1; di++) { for (int dj = -1; dj <= 1; dj++) { int cur_i = pxlheight + di; int cur_j = pxlwidth + dj; // 单独判断坐标合法性,不合法直接跳过,不终止整个循环 if (cur_i >= 0 && cur_i < height && cur_j >=0 && cur_j < width) { sumRed += copy[cur_i][cur_j].rgbtRed; sumGreen += copy[cur_i][cur_j].rgbtGreen; sumBlue += copy[cur_i][cur_j].rgbtBlue; count++; } } } // 转浮点数计算平均值再取整,避免整数截断误差 res.rgbtRed = round((float)sumRed / count); res.rgbtGreen = round((float)sumGreen / count); res.rgbtBlue = round((float)sumBlue / count); return res; }
补充说明:你一开始写的
calloc分配副本的逻辑是正确的,不存在内存分配问题,不需要修改。
内容的提问来源于stack exchange,提问作者Mimoliere
相关产品推荐
相关产品推荐

