无法向二叉树插入节点:代码实现故障排查求助
核心问题分析
你的代码存在三个关键错误,直接导致插入节点后树始终为空,甚至会引发内存错误:
1. 指针传递方式错误
C语言中函数参数是值传递,你当前的BVSCreate_function和BVSInsert_function使用TNodef *rootPtr作为参数,函数内部修改的只是这个形参的副本,完全不会影响外部的实参指针。比如调用BVSCreate_function(rootPtr, token)时,函数里的rootPtr = newPtr只是修改了局部变量,外部的根指针根本没被更新,所以树始终是空的。
解决方式:改用指针的指针(TNodef **)传递,这样才能修改外部指针的指向。
2. BVSCreate_function的内存管理错误
你在函数中先通过malloc分配了newPtr,但紧接着执行newPtr = &init,直接丢弃了malloc的内存(造成内存泄漏),而且init是栈上的局部变量,函数执行完毕后会被销毁,newPtr变成野指针,后续访问会触发未定义行为。
同时,newPtr->content指向的initStr也是栈上的局部string变量,同样会在函数退出后失效。
解决方式:直接使用malloc分配的节点内存,同时为content指向的string结构体也分配堆内存,避免使用栈上的局部变量。
3. strCpyStr的空指针访问问题
当newPtr->content->str为NULL时,第一次调用strCpyStr,如果token.content的长度大于0,strcpy会尝试向NULL指针写入数据,直接触发程序崩溃。
解决方式:在strCpyStr中处理str为NULL的情况,确保写入前有合法的内存空间。
修正后的代码示例
修正后的节点创建与插入函数
void BVSCreate_function(TNodef **rootPtr, function_save token) { // 为二叉树节点分配堆内存 TNodef *newPtr = malloc(sizeof(struct tnodef)); if (newPtr == NULL) { fprintf(stderr, "99"); return; } // 为content指向的string结构体分配堆内存 newPtr->content = malloc(sizeof(string)); if (newPtr->content == NULL) { free(newPtr); fprintf(stderr, "99"); return; } // 初始化string结构体 newPtr->content->str = NULL; newPtr->content->length = 0; newPtr->content->alloc = 0; // 初始化节点其他字段 newPtr->leftPtr = NULL; newPtr->rightPtr = NULL; newPtr->return_type = token.ret_value; newPtr->parameters = token.param_count; // 复制字符串内容,失败则回滚内存分配 if (strCpyStr(newPtr->content, token.content) != 0) { free(newPtr->content->str); free(newPtr->content); free(newPtr); fprintf(stderr, "String copy failed"); return; } // 修改外部指针的指向 *rootPtr = newPtr; } void BVSInsert_function(TNodef **rootPtr, function_save token) { if (*rootPtr == NULL) { BVSCreate_function(rootPtr, token); } else { int cmpResult = strCmpStr(token.content, (*rootPtr)->content); if (cmpResult < 0) { BVSInsert_function(&((*rootPtr)->leftPtr), token); } else if (cmpResult > 0) { BVSInsert_function(&((*rootPtr)->rightPtr), token); } // 字符串相等的情况可根据需求处理(如忽略、更新节点) } }
修正后的strCpyStr函数
int strCpyStr(string *s1, string *s2) { int len2 = s2->length; // 处理空指针或内存不足的情况 if (s1->str == NULL || len2 > s1->alloc) { char *newStr = realloc(s1->str, len2 + 1); if (newStr == NULL) { return 1; } s1->str = newStr; s1->alloc = len2 + 1; } // 复制字符串,处理空字符串场景 if (len2 == 0) { s1->str[0] = '\0'; } else { strcpy(s1->str, s2->str); } s1->length = len2; // 注释说明length是字符串长度,不包含终止符,因此无需+1 return 0; }
内容的提问来源于stack exchange,提问作者Marcin Sochacki

