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

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;
}

额外建议

  1. 程序结束前需递归遍历二叉树,释放每个节点的字符串内存和结构体本身,避免内存泄漏。
  2. 使用scanf读取字符串时,始终限制输入长度(如%99s),防止缓冲区溢出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:24:59