递归构建文件管理器路径字符串时程序崩溃,求C代码排查修复
问题分析与修复
你的代码存在几个致命问题,直接导致程序卡死或崩溃:
- 无限递归:递归调用
getPath(root, actual)时没有传入父节点actual->pPA,函数会反复调用自身,永远无法终止,最终导致栈溢出或程序无响应。 - 返回局部栈内存:
resp是函数内的局部数组,函数执行完毕后栈空间会被回收,返回的指针指向无效内存,后续使用会引发未定义行为(崩溃或乱码)。 - 未初始化字符串就使用
strcat:resp初始值是随机垃圾数据,strcat依赖目标字符串的'\0'结尾来确定追加位置,这里直接调用会读取非法内存,导致程序异常。 - 拼接逻辑颠倒:你需要先获取父节点的路径,再追加当前节点名称,原代码的拼接顺序完全错误。
修复方案(动态内存版)
使用malloc动态分配内存,避免返回局部变量,同时修正递归逻辑和拼接顺序:
#include <stdlib.h> #include <string.h> char *getPath(lnodo *root, lnodo *actual) { // 递归终止:到达根节点 if (actual->pPA == NULL) { // 为根节点路径分配内存,长度为名称长度+2(加"/"和结束符) char *resp = malloc(strlen(actual->Nom) + 2); if (resp == NULL) return NULL; // 内存分配失败处理 strcpy(resp, actual->Nom); strcat(resp, "/"); return resp; } // 先递归获取父节点的路径 char *parent_path = getPath(root, actual->pPA); if (parent_path == NULL) return NULL; // 计算当前路径总长度:父路径长度 + 当前节点名称长度 + 2(加"/"和结束符) size_t total_len = strlen(parent_path) + strlen(actual->Nom) + 2; char *resp = realloc(parent_path, total_len); if (resp == NULL) { free(parent_path); // 内存分配失败,释放父节点路径内存 return NULL; } // 追加当前节点名称和分隔符 strcat(resp, actual->Nom); strcat(resp, "/"); return resp; } void path(lnodo *root, lnodo *actual) { char *current_path = getPath(root, actual); if (current_path != NULL) { printf("%s\n", current_path); free(current_path); // 记得释放动态分配的内存,避免泄漏 } }
替代方案(调用者提供缓冲区)
如果不想用动态内存,可以让调用者传入缓冲区和最大长度,更安全且避免内存泄漏:
#include <string.h> // 返回值:成功返回缓冲区指针,失败返回NULL(比如缓冲区不足) char *getPath(lnodo *root, lnodo *actual, char *buf, size_t buf_size) { // 递归终止:到达根节点 if (actual->pPA == NULL) { if (strlen(actual->Nom) + 2 > buf_size) return NULL; strcpy(buf, actual->Nom); strcat(buf, "/"); return buf; } // 先递归填充父节点路径 if (!getPath(root, actual->pPA, buf, buf_size)) { return NULL; } // 检查剩余空间是否足够容纳当前节点名称和分隔符 size_t current_len = strlen(buf); if (current_len + strlen(actual->Nom) + 2 > buf_size) { return NULL; } // 追加当前节点信息 strcat(buf, actual->Nom); strcat(buf, "/"); return buf; } void path(lnodo *root, lnodo *actual) { char buf[400]; if (getPath(root, actual, buf, sizeof(buf))) { printf("%s\n", buf); } else { printf("路径过长,缓冲区不足\n"); } }
内容的提问来源于stack exchange,提问作者roguesquid
相关产品推荐
相关产品推荐

