自定义cell类型二维数组resizeArray函数异常排查求助
问题排查与修复:自定义二维数组resize函数异常
问题描述
尝试编写resizeArray函数用于调整自定义cell类型二维数组的大小,内存分配失败时返回错误信息,但代码无法正常运行,编译器无警告,怀疑返回指针类型不匹配。
原始代码
#include <stdio.h> #include <stdlib.h> typedef struct { int variable_1; int variable_2; char character; } cell; unsigned long max(unsigned long a, unsigned long b) { if (a >= b) return a; else return b; } void initialiseArray(unsigned long rows, unsigned long columns, cell array[rows][columns]) { for (unsigned long i = 0; i < rows; i = i + 1) for (unsigned long j = 0; j < columns; j = j + 1) { array[i][j].variable_1 = 0; array[i][j].variable_2 = 0; array[i][j].character = ' '; } } cell *resizeArray(unsigned long rows, unsigned long columns, unsigned long *array_rows, unsigned long *array_columns, cell array[*array_rows][*array_columns]) { if (rows > *array_rows || columns > *array_columns) { unsigned long new_array_rows = max(rows, *array_rows); unsigned long new_array_columns = max(columns, *array_columns); cell (*new_array)[new_array_rows][new_array_columns] = malloc(sizeof *new_array); if (new_array == NULL) { printf("Error in \"resize\": Memory could not be allocated.\n"); return NULL; } else free(array); *array_rows = new_array_rows; *array_columns = new_array_columns; return new_array; } } int main(void) { unsigned long array_rows = 10; unsigned long array_columns = 15; cell (*array)[array_rows][array_columns] = malloc(sizeof *array); if (array == NULL) { printf("Error in \"main\": Memory could not be allocated.\n"); return 3; } cell *new_array = resizeArray(15, 15, &array_rows, &array_columns, *array); if (new_array == NULL) printf("Memory error. We stop the program.\n"); return -1; array = new_array; initialiseArray(array_rows, array_columns, *array); return 0; }
核心问题分析
指针类型严重不匹配
resizeArray函数声明返回cell*,但实际返回的是cell (*)[new_array_rows][new_array_columns](指向二维变长数组的指针),两种类型完全不兼容。编译器未警告是因为隐式指针转换,但这会导致未定义行为,是代码崩溃的核心原因。
main函数逻辑错误
return -1;语句直接写在错误判断之后,导致后续的array = new_array;和初始化代码永远不会执行,程序直接退出。
内存释放错误
- 函数参数中的
cell array[*array_rows][*array_columns]会被编译器退化为cell (*)[*array_columns](指向一维数组的指针),此时free(array)释放的是数组首元素的指针,而非原来在main中分配的二维数组指针,会导致内存泄漏或双重释放问题。
- 函数参数中的
函数无返回值分支
- 当不需要扩容时,
resizeArray没有返回值,触发未定义行为。
- 当不需要扩容时,
修复后的代码
#include <stdio.h> #include <stdlib.h> typedef struct { int variable_1; int variable_2; char character; } cell; unsigned long max(unsigned long a, unsigned long b) { return (a >= b) ? a : b; } void initialiseArray(unsigned long rows, unsigned long columns, cell (*array)[columns]) { for (unsigned long i = 0; i < rows; ++i) for (unsigned long j = 0; j < columns; ++j) { array[i][j].variable_1 = 0; array[i][j].variable_2 = 0; array[i][j].character = ' '; } } // 返回指向一维数组的指针(模拟二维数组),统一类型 cell (*resizeArray(unsigned long rows, unsigned long columns, unsigned long *array_rows, unsigned long *array_columns, cell (*old_array)[*array_columns]))[] { // 不需要扩容时直接返回原数组 if (rows <= *array_rows && columns <= *array_columns) { return old_array; } unsigned long new_rows = max(rows, *array_rows); unsigned long new_cols = max(columns, *array_columns); // 分配新内存:按元素总数分配,避免变长数组指针的兼容性问题 cell (*new_array)[new_cols] = malloc(sizeof(cell) * new_rows * new_cols); if (new_array == NULL) { printf("Error in \"resize\": Memory could not be allocated.\n"); return NULL; } // 释放原数组内存 free(old_array); // 更新行列数 *array_rows = new_rows; *array_columns = new_cols; return new_array; } int main(void) { unsigned long array_rows = 10; unsigned long array_columns = 15; // 初始分配:用指向一维数组的指针模拟二维数组,简化类型处理 cell (*array)[array_columns] = malloc(sizeof(cell) * array_rows * array_columns); if (array == NULL) { printf("Error in \"main\": Memory could not be allocated.\n"); return 3; } cell (*new_array)[array_columns] = resizeArray(15, 15, &array_rows, &array_columns, array); if (new_array == NULL) { printf("Memory error. We stop the program.\n"); free(array); return -1; } // 更新数组指针并初始化 array = new_array; initialiseArray(array_rows, array_columns, array); // 后续业务逻辑... // 最后释放内存 free(array); return 0; }
修复说明
统一指针类型
- 将数组改为用
cell (*)[cols](指向一维数组的指针)模拟二维数组,resizeArray返回同类型指针,彻底解决类型不匹配问题。
- 将数组改为用
修正main函数逻辑
- 仅在内存分配失败时执行
return -1;,确保正常流程下初始化代码能执行。
- 仅在内存分配失败时执行
修复内存管理
- 直接传入原数组的指针进行释放,避免退化后的指针错误释放问题;补充无需扩容时的返回逻辑,消除无返回值的未定义行为。
优化内存分配方式
- 按元素总数分配内存,避免变长数组指针的兼容性限制,提升代码可移植性。
内容的提问来源于stack exchange,提问作者3nondatur
相关产品推荐
相关产品推荐

