C语言线性回归程序read_points函数动态内存分配异常排查(malloc校验和错误)
看起来你遇到了动态内存里超常见的内存越界写入问题,久不碰C的话确实很容易踩这个坑,我帮你一步步理清楚~
首先,你看到的Incorrect checksum for freed object错误,本质是malloc的内部校验机制触发了警报:malloc会在分配的内存块前后加一些校验标记,用来检测内存越界、重复释放这类非法操作。当你不小心写了超出数组范围的内存时,就会把这些标记搞坏,后续的内存操作(比如realloc、free)就会抛出你看到的错误。
现在看你的read_points代码,核心问题出在循环的执行顺序上:
while(scanf("%lf %lf", &arr[i].x, &arr[i].y)==2){ if (i>= cap){ // 扩容逻辑 } i++; }
举个具体的例子:当cap=10,i=9的时候,这一轮循环会把数据写入arr[9](这是合法的,数组下标范围是0~9),然后i变成10。下一轮循环一开始,你直接用scanf往arr[10].x和arr[10].y写数据,但此时cap还是10,数组的有效下标最多到9,arr[10]已经是超出分配范围的内存了!这时候写入就会破坏malloc的校验标记,等到后面执行扩容的realloc,或者之后你free这个数组的时候,就会触发校验和错误。
修复方案
调整循环内的逻辑顺序,先检查容量是否足够,再往数组里写数据,或者先把输入读到临时变量里,确认容量足够后再赋值,就能避免越界写入。这里给你两种修复后的代码版本:
版本1:先读临时变量,确认容量后再赋值(更安全)
point_t* read_points(int* count){ int cap = 10; int i = 0; point_t* arr = malloc(cap*sizeof(point_t)); if (!arr){ fprintf(stderr, "malloc() failed!\n"); exit(1); } while(1){ // 先检查是否需要扩容 if (i >= cap){ cap *=2; point_t* temp = realloc(arr, cap*sizeof(point_t)); if(!temp){ fprintf(stderr, "realloc() failed!\n"); free(arr); exit(1); } arr = temp; } // 先把输入读到临时变量 double x, y; if (scanf("%lf %lf", &x, &y) != 2){ break; } // 读取成功再写入数组 arr[i].x = x; arr[i].y = y; i++; } *count = i; return arr; }
版本2:直接调整循环顺序,先扩容再写入
point_t* read_points(int* count){ int cap = 10; int i = 0; point_t* arr = malloc(cap*sizeof(point_t)); if (!arr){ fprintf(stderr, "malloc() failed!\n"); exit(1); } while(1){ // 先检查容量:i等于cap时先扩容,再处理输入 if (i >= cap) { cap *= 2; point_t* temp = realloc(arr, cap * sizeof(point_t)); if (!temp) { fprintf(stderr, "realloc() failed!\n"); free(arr); exit(1); } arr = temp; } // 写入当前下标,失败则退出循环 if (scanf("%lf %lf", &arr[i].x, &arr[i].y) != 2) { break; } i++; } *count = i; return arr; }
额外提醒
另外,之后在使用完read_points返回的数组时,一定要记得用free()释放,避免内存泄漏,但你当前的错误和释放无关,完全是提前越界写入破坏了malloc的校验信息导致的。
这样调整后,应该就能解决你遇到的错误了,要是还有其他问题随时问~
内容来源于stack exchange

