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); } }
关键修改点说明
- 把
findpath的参数改为char ***res,同时传递resIdx和sum的指针,彻底去掉全局变量。 - 在
realloc后将新指针赋值给*res,确保上层函数的指针同步更新。 - 增加了
malloc和realloc的返回值检查,避免空指针访问。 - 扩大了路径缓冲区的大小,防止字符串溢出。
- 简化了返回值的写法,
return res和return &res[0]等价,但更清晰。
内容的提问来源于stack exchange,提问作者vivek
相关产品推荐
相关产品推荐

