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

C语言递归收集树叶子节点指针时出现段错误问题求助

问题排查:递归遍历树形结构收集叶子节点时的段错误

调用init_model()函数时,尝试递归遍历树形结构,将最底层TreeNode(叶子节点)的指针添加到TreeNode指针类型的动态数组中,但遍历数组打印时出现段错误。相关代码如下:

void rec_find_inputs(TreeNode* root, TreeNode** arr, int* len_arr) {
    if (!(root->num_children)) {
        arr = realloc(*arr, *len_arr * sizeof(TreeNode*));
        arr[*len_arr] = root;
        (*len_arr)++;
    } else {
        for (int i = 0; i < root->num_children; i++) {
            rec_find_inputs(root->children[i], arr, len_arr);
        }
    }
}


void init_model(TreeNode* neuron_config) {
    int rec_params_len = 0;
    TreeNode** rec_params_arr = (TreeNode**) malloc(sizeof(TreeNode*) * 1);

    rec_find_inputs(neuron_config, rec_params_arr, &rec_params_len);

    printf("--------------\n");
    printf("%d\n", rec_params_len);
    for (int i = 0; i < rec_params_len; i++) {
        printf("%f\n", rec_params_arr[i]->data);
    }
}

问题原因分析

  • 指针传递错误:rec_find_inputs函数中的arr是按值传递的二级指针,realloc修改的是函数内部的局部指针变量,并不会影响外部的rec_params_arr。当realloc重新分配内存后,局部的arr指向新地址,但外部的rec_params_arr仍然指向旧的内存块,后续操作会导致野指针访问或内存越界,最终触发段错误。
  • 内存分配大小错误:代码中realloc(*arr, *len_arr * sizeof(TreeNode*))的计算逻辑错误。当*len_arr为0时,会分配0字节的内存,此时执行arr[*len_arr] = root会直接越界访问非法内存;即使*len_arr不为0,当前分配的空间也只能容纳现有数量的元素,无法新增一个叶子节点的指针。

修正后的代码

修正递归收集函数

void rec_find_inputs(TreeNode* root, TreeNode*** arr, int* len_arr) {
    // 先判断root是否为空,避免空指针访问
    if (!root) {
        return;
    }
    if (!(root->num_children)) {
        // 重新分配内存,容量为当前长度+1,确保能容纳新元素
        *arr = realloc(*arr, (*len_arr + 1) * sizeof(TreeNode*));
        // 使用*arr访问外部传入的数组指针,赋值新的叶子节点
        (*arr)[*len_arr] = root;
        (*len_arr)++;
    } else {
        for (int i = 0; i < root->num_children; i++) {
            // 传递数组指针的地址,确保递归中能修改外部数组的地址
            rec_find_inputs(root->children[i], arr, len_arr);
        }
    }
}

修正初始化函数

void init_model(TreeNode* neuron_config) {
    int rec_params_len = 0;
    // 初始可以分配1个元素空间,也可以直接设为NULL(realloc会自动处理)
    TreeNode** rec_params_arr = malloc(sizeof(TreeNode*) * 1);

    // 传入数组指针的地址,让递归函数能修改它
    rec_find_inputs(neuron_config, &rec_params_arr, &rec_params_len);

    printf("--------------\n");
    printf("%d\n", rec_params_len);
    for (int i = 0; i < rec_params_len; i++) {
        printf("%f\n", rec_params_arr[i]->data);
    }

    // 释放动态分配的内存,避免内存泄漏
    free(rec_params_arr);
}

额外注意事项

  • 新增了if (!root)的判断,防止树形结构中存在空节点时触发空指针访问错误。
  • 使用完动态数组后必须调用free(rec_params_arr),避免内存泄漏。
  • 初始的malloc可以替换为TreeNode** rec_params_arr = NULL;,因为realloc(NULL, size)的效果等同于malloc(size),这样代码更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 21:13:29