C语言realloc()无效下一个大小错误及栈实现异常求助
问题分析与解决方案
新年快乐!咱们来一步步搞定你遇到的内存错误和奇怪输出问题~
核心问题:C语言的指针是值传递
你代码里的resize函数存在一个关键错误:你传递的是指针的副本,函数内部修改指针不会影响外部的原指针。
具体来说:
- 当你在
main里调用resize(sizeOfArray, myArray)时,myArray是按值传递给resize的——函数里的myArray只是一个临时副本,和main里的myArray指向同一块内存,但本身是两个不同的变量。 - 当
realloc成功返回新的内存地址u后,你把resize里的myArray赋值为u,但这个修改只在resize函数内部有效,main里的myArray仍然指向原来的旧内存块。 - 旧内存块可能已经被
realloc回收,此时main里的myArray就变成了野指针,后续的push操作相当于往已经被释放的内存里写数据,这属于未定义行为——有时候看似正常,有时候会触发realloc(): invalid next size错误,有时候会出现像你看到的数值错乱(比如第二个元素变成0),这些都是野指针导致的随机结果。
为什么取消printf注释会有不同表现?
这也是未定义行为的典型特征:printf的调用会改变程序的内存布局(比如栈上的变量位置、堆的分配状态),刚好掩盖了一部分错误,或者触发了另一种错误表现,但本质问题还是野指针没有被修复。
解决方案:传递指向指针的指针
要让resize函数能修改main里的myArray指针,你需要把参数改成指向指针的指针(int **myArray),这样就能直接操作外部的指针变量了。
修改后的代码如下:
#include <stdio.h> #include <stdlib.h> // 修改参数为指向指针的指针 void resize(int *sizeOfArray, int **myArray){ int *u; *sizeOfArray *= 2; u = (int *)realloc(*myArray, sizeof(int)*(*sizeOfArray)); if(u == NULL){ printf("Error!\n"); exit(1); } *myArray = u; // 直接修改外部的myArray指针 } void push(int *pos, int *myArray, int *sizeOfArray){ if(*pos == *sizeOfArray) { // 传入myArray的地址 resize(sizeOfArray, &myArray); } *(myArray + (*pos)) = *pos; (*pos)++; } void pop(int *pos){ (*pos)--; } int main(){ int *myArray, pos = 0, i, sizeOfArray = 5; myArray = (int *)malloc(sizeof(int)*sizeOfArray); *(myArray + pos)= pos; pos++; *(myArray + pos) = pos; pos++; *(myArray + pos) = pos; pos++; // 不管有没有这个printf,程序都能正常运行 // for(i = 0;i < pos;i++) printf("%d\n",*(myArray+i)); push(&pos, myArray, &sizeOfArray); push(&pos, myArray, &sizeOfArray); push(&pos, myArray, &sizeOfArray); push(&pos, myArray, &sizeOfArray); // pop(&pos); // pop(&pos); // pop(&pos); for(i = 0;i<pos;i++) printf("** %d\n",*(myArray+i)); return 0; }
修改后的原理
- 现在
resize接收的是myArray的地址(int **类型),通过*myArray = u,直接把realloc得到的新地址赋值给main里的myArray变量。 - 后续的
push操作都会使用新的内存块,不会再访问已经被释放的旧内存,也就解决了野指针问题,不管有没有printf注释,都能输出正确的结果:** 0 ** 1 ** 2 ** 3 ** 4 ** 5 ** 6
内容的提问来源于stack exchange,提问作者moijoune
相关产品推荐
相关产品推荐

