C语言BMP图像翻转结构体数组赋值触发Segmentation fault求助
段错误触发原因及修复方案
核心问题点
- 栈空间溢出(最高概率触发)
你在函数栈帧里声明的struct pixel data_array[image->header->height][image->header->width]是变长数组(VLA),完全占用栈空间。普通进程栈默认大小仅1~8MB,只要图片分辨率稍高(比如1080p RGB图就需要约6MB像素空间),就会直接撑爆栈触发段错误。 - 堆分配返回值未校验
两次calloc调用都没有判断返回值是否为NULL:- 分配
transformed失败时,后续给transformed->header赋值属于解引用空指针 - 分配
transformed_data失败时,注释行之后的循环直接给空指针偏移赋值,必然触发段错误
- 分配
- 结构体内存分配写法不健壮
calloc(1, sizeof(image->data) + sizeof(image->header))计算的是两个指针的大小,仅在当前struct bmp_image仅包含这两个指针成员时刚好正确。后续如果给结构体新增成员,会直接导致分配内存不足,出现越界访问。 - 冗余拷贝放大风险
先把像素转存到栈上二维数组、再拷贝到堆内存的逻辑完全多余,既浪费栈空间,又增加了不必要的拷贝步骤。
修复后可运行代码
struct bmp_image *flip_horizontally(const struct bmp_image *image) { // 入参全量校验,避免空指针访问 if (image == NULL || image->header == NULL || image->data == NULL) { return NULL; } const int width = (int)image->header->width; const int height = (int)image->header->height; const size_t total_pixels = (size_t)width * height; // 直接分配结构体本身的大小,避免手动计算大小出错 struct bmp_image *transformed = calloc(1, sizeof(struct bmp_image)); if (transformed == NULL) { return NULL; } transformed->header = image->header; // 直接分配目标像素数组,校验分配结果 struct pixel *transformed_data = calloc(total_pixels, sizeof(struct pixel)); if (transformed_data == NULL) { free(transformed); return NULL; } int index = 0; // 直接边翻转边写入目标数组,省掉栈上临时数组 for (int i = 0; i < height; i++) { for (int j = width - 1; j >= 0; j--) { transformed_data[index] = image->data[i * width + j]; index++; } } transformed->data = transformed_data; return transformed; }
补充说明
你怀疑注释行之后的循环段触发问题,本质是这段循环访问的transformed_data要么是分配失败的空指针,要么是之前栈上VLA溢出已经破坏了内存结构,导致后续流程访问非法地址。如果需要实现垂直翻转,只需要把外层循环的i从height-1倒序遍历到0即可。
内容的提问来源于stack exchange,提问作者Matej
相关产品推荐
相关产品推荐

