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

LeetCode 257 二叉树路径问题中realloc操作引发段错误的排查求助

分析你的段错误原因及修复方案

你的代码出现段错误的核心原因是指针传递方式错误,导致realloc后的新指针没有同步到上层函数,另外还有几个潜在问题可能加剧这个问题,我逐一给你拆解:

1. 致命问题:realloc后的指针无法同步到上层

你在findpath函数中接收的char **res是按值传递的——也就是说,函数里的res只是上层binaryTreePaths中res指针的一个副本。当你执行res = realloc(res, ...)时,你修改的只是这个局部副本的指向,而binaryTreePaths里的原始res指针仍然指向已经被realloc释放的旧内存块。后续访问这个旧内存就会直接触发段错误。

修复方式:传递指针的指针

要让findpath能修改上层的res指针,你需要传递char ***res(指针的指针),这样函数里就能直接修改上层指针的指向。

2. 其他潜在问题

  • 全局变量的风险:你用了全局变量sum和resIdx,虽然在binaryTreePaths里做了重置,但LeetCode的测试环境可能会连续运行多个测试用例,全局变量的状态残留可能导致奇怪的问题,最好改成通过指针传递局部变量。
  • 内存分配未做错误检查:malloc和realloc都可能返回NULL(内存分配失败),直接使用会触发崩溃。
  • 路径数组ls的覆盖风险:binaryTreePaths里的ls是局部数组,递归时左右分支会共享这个数组,虽然当前逻辑下因为到叶子才处理路径暂时没问题,但如果逻辑变更容易出bug。
  • 路径缓冲区大小不足:你给每个路径分配了100字节,但如果二叉树深度较大(比如超过10层),路径字符串会溢出这个缓冲区。

修复后的完整代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */

void findpath(struct TreeNode* root, int *ls, int ls_idx, char ***res, int *resIdx, int *sum);

char ** binaryTreePaths(struct TreeNode* root, int* returnSize){
    if (root == NULL) {
        *returnSize = 0;
        return NULL;
    }
    int resIdx = 0;
    int sum = 10;
    // 分配初始内存并检查是否成功
    char **res = malloc(sizeof(char *) * sum);
    if (!res) {
        *returnSize = 0;
        return NULL;
    }
    int ls[100]; // 假设二叉树深度不超过100,若不确定可改用动态数组
    findpath(root, ls, 0, &res, &resIdx, &sum);
    *returnSize = resIdx;
    return res; // 直接返回res即可,无需&res[0]
}

void findpath(struct TreeNode* root, int *ls, int ls_idx, char ***res, int *resIdx, int *sum) {
    char temp[1024]; // 扩大缓冲区避免溢出
    int l = 0, i = 0;
    if (root->left == NULL && root->right == NULL) {
        ls[ls_idx] = root->val;
        ls_idx++;
        // 检查是否需要扩容
        if (*resIdx >= *sum) {
            *sum += 10;
            char **new_res = realloc(*res, sizeof(char *) * (*sum));
            if (!new_res) {
                // 内存分配失败,可在这里做清理逻辑,比如释放已分配的路径
                return;
            }
            *res = new_res; // 更新上层的res指针
        }
        // 分配路径内存并检查
        (*res)[*resIdx] = malloc(sizeof(char) * 1024);
        if (!(*res)[*resIdx]) {
            return;
        }
        // 拼接路径字符串
        while (i < ls_idx) {
            if (i == 0) {
                l += sprintf(&temp[l], "%d", ls[i]);
            } else {
                l += sprintf(&temp[l], "->%d", ls[i]);
            }
            i++;
        }
        strcpy((*res)[*resIdx], temp);
        (*resIdx)++;
        return;
    }
    ls[ls_idx] = root->val;
    if (root->left != NULL) {
        findpath(root->left, ls, ls_idx + 1, res, resIdx, sum);
    }
    if (root->right != NULL) {
        findpath(root->right, ls, ls_idx + 1, res, resIdx, sum);
    }
}

关键修改点说明

  1. 把findpath的参数改为char ***res,同时传递resIdx和sum的指针,彻底去掉全局变量。
  2. 在realloc后将新指针赋值给*res,确保上层函数的指针同步更新。
  3. 增加了malloc和realloc的返回值检查,避免空指针访问。
  4. 扩大了路径缓冲区的大小,防止字符串溢出。
  5. 简化了返回值的写法,return res和return &res[0]等价,但更清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 15:13:12