You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:06:40