C语言二叉树节点数据写入失败求助:程序执行至Checkpoint3后崩溃
问题分析与修复方案
核心问题1:结构体字符串指针未分配内存
结构体struct produto中的nome、marca、categoria是字符指针,但你仅分配了结构体本身的内存,未为这些指针分配存储字符串的实际空间。直接调用strcpy会向野指针指向的未知内存写入数据,触发内存访问错误,导致程序进入novoproduto函数后执行strcpy时直接崩溃,因此无法输出checkpoint4。
核心问题2:二叉树递归插入逻辑错误
在inserirelemento函数中,当待插入的codigo大于当前节点的codigo时,应该递归处理右子树(head->dir),但代码错误地传入了head->esq,这会导致后续插入操作出现无限递归,最终引发栈溢出(对应错误码0xC00000FD)。
次要问题:根节点未初始化
main函数中produto * head;未初始化为NULL,导致第一次调用inserirelemento时,head是野指针,可能触发未定义行为。
修复后的完整代码实现
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 100 // 定义字符串最大长度 typedef struct produto produto; struct produto{ int codigo, estoque; char *nome, *marca, *categoria; float preco; produto *dir, *esq; }; produto * novoproduto(produto * head, int codigo, int estoque, char *nome, char *marca, char *categoria, float preco){ head->codigo = codigo; head->estoque = estoque; // 为每个字符串分配内存,包含终止符空间 head->nome = (char*)malloc(strlen(nome) + 1); head->marca = (char*)malloc(strlen(marca) + 1); head->categoria = (char*)malloc(strlen(categoria) + 1); // 检查内存分配是否成功 if(!head->nome || !head->marca || !head->categoria){ printf("内存分配失败\n"); exit(1); } strcpy(head->nome, nome); strcpy(head->marca, marca); strcpy(head->categoria, categoria); head->preco = preco; // 初始化左右子节点为NULL head->esq = NULL; head->dir = NULL; printf("checkpoint 4\n"); return head; } produto * inserirelemento(produto *head, int codigo, int estoque, char nome[], char marca[], char categoria[], float preco){ if(head != NULL){ if(codigo < head->codigo){ head->esq = inserirelemento(head->esq, codigo, estoque, nome, marca, categoria, preco); return head; }else if(codigo > head->codigo){ // 修正递归逻辑:处理右子树 head->dir = inserirelemento(head->dir, codigo, estoque, nome, marca, categoria, preco); return head; }else{ // 已存在相同codigo的节点,直接返回 return head; } }else{ printf("checkpoint 3\n"); head = (struct produto *) malloc(sizeof(struct produto)); head = novoproduto(head, codigo, estoque, nome, marca, categoria, preco); return head; } } produto * inserir(produto *head, int codigo, int estoque, char nome[], char marca[], char categoria[], float preco){ printf("checkpoint 2\n"); head = inserirelemento(head, codigo, estoque, nome, marca, categoria, preco); return head; } produto * inserirnovo(produto *head){ int codigo, estoque; char nome[MAX], marca[MAX], categoria[MAX]; float preco; printf("insira um codigo pro produto\n"); scanf("%d", &codigo); printf("insira um nome pro produto\n"); scanf("%99s", nome); // 限制输入长度避免缓冲区溢出 printf("insira uma marca pro produto\n"); scanf("%99s", marca); printf("insira uma categoria pro produto\n"); scanf("%99s", categoria); printf("insira um estoque pro produto\n"); scanf("%d", &estoque); printf("insira um preco pro produto\n"); scanf("%f", &preco); printf("checkpoint 1\n"); return inserir(head, codigo, estoque, nome, marca, categoria, preco); } int main(){ // 初始化根节点为NULL produto * head = NULL; head = inserirnovo(head); return 0; }
额外建议
- 程序结束前需递归遍历二叉树,释放每个节点的字符串内存和结构体本身,避免内存泄漏。
- 使用
scanf读取字符串时,始终限制输入长度(如%99s),防止缓冲区溢出。
内容的提问来源于stack exchange,提问作者Davi Franke
相关产品推荐
相关产品推荐

