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

嵌套函数中调用realloc重分配内存失败的问题求助

嵌套函数中realloc失效的问题分析与修复

问题现象

编写了一个向数组追加对象指针的函数pushNode,但在该嵌套函数内调用realloc无法正确重分配内存;而在最初分配内存的主函数中直接调用realloc则一切正常。运行代码会触发内存错误。

原代码

#include <stdlib.h>

typedef struct Node
{
    char ch;
    int freq;
    struct Node *left, *right;

} Node;

Node *newNode(char ch, int freq, Node *left, Node *right)
{
    Node *node = (Node *)malloc(sizeof(Node));
    node->ch = ch;
    node->freq = freq;
    node->left = left;
    node->right = right;

    return node;
};

void pushNode(Node **nodes, Node *node, int *nodesCount)
{
    nodes = (Node **)realloc(nodes, ++(*nodesCount) * sizeof(Node *)); // error
    nodes[*nodesCount - 1] = node;
}

int main()
{
    int nodesCount = 0;
    Node **nodes = (Node **)calloc(0, sizeof(Node *));

    Node *node = newNode('\0', 0, NULL, NULL);
    pushNode(nodes, node, &nodesCount);

    for (int i = 0; i < 256; i++)
    {
        node = newNode((char)i, i, NULL, NULL);
        // pushNode(nodes, node, &nodesCount);
        nodes = (Node **)realloc(nodes, ++nodesCount * sizeof(Node *)); // no error
        nodes[nodesCount - 1] = node;
    }

    free(nodes);

    return 0;
}

错误信息

test(94309,0x1ec9f2500) malloc: *** error for object 0x60000020c020: pointer being realloc'd was not allocated
test(94309,0x1ec9f2500) malloc: *** set a breakpoint in malloc_error_break to debug

原因分析

  • 核心问题:参数传递方式错误:pushNode的参数Node **nodes是值传递,传递的是主函数中nodes指针的副本。在pushNode里调用realloc修改的是这个副本的地址,主函数里的原nodes指针完全不会更新。
  • 内存访问违规:当realloc需要重新分配内存时,会释放原指针指向的内存块,但主函数里的nodes仍持有这个已被释放的无效地址。后续主函数再用这个地址调用realloc,就会触发内存错误——因为这块内存已经不属于当前程序。

解决方法

要让pushNode能修改主函数里的nodes指针,必须传递指针的指针的指针(Node ***nodes),这样才能在函数内部修改外层的指针变量。

修正后的代码

#include <stdlib.h>

typedef struct Node
{
    char ch;
    int freq;
    struct Node *left, *right;

} Node;

Node *newNode(char ch, int freq, Node *left, Node *right)
{
    Node *node = (Node *)malloc(sizeof(Node));
    node->ch = ch;
    node->freq = freq;
    node->left = left;
    node->right = right;

    return node;
};

// 修改参数为Node ***nodes,实现对主函数指针的修改
void pushNode(Node ***nodes, Node *node, int *nodesCount)
{
    // 解引用获取主函数中的nodes指针,再调用realloc更新地址
    *nodes = (Node **)realloc(*nodes, ++(*nodesCount) * sizeof(Node *));
    (*nodes)[*nodesCount - 1] = node;
}

int main()
{
    int nodesCount = 0;
    Node **nodes = (Node **)calloc(0, sizeof(Node *));

    Node *node = newNode('\0', 0, NULL, NULL);
    // 传递nodes的地址(即Node ***类型)
    pushNode(&nodes, node, &nodesCount);

    for (int i = 0; i < 256; i++)
    {
        node = newNode((char)i, i, NULL, NULL);
        // 使用修复后的pushNode函数
        pushNode(&nodes, node, &nodesCount);
    }

    // 补充释放每个Node对象的内存,避免泄漏
    for (int i = 0; i < nodesCount; i++)
    {
        free(nodes[i]);
    }
    free(nodes);

    return 0;
}

补充说明

  • 修正后的pushNode通过*nodes直接操作主函数里的指针变量,确保realloc后的新地址能同步到主函数。
  • 原代码遗漏了对每个Node对象的内存释放,修正后补充了这一步,避免内存泄漏。

内容的提问来源于stack exchange,提问作者lian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:15:11