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

C语言二叉树程序输出正常后触发Segmentation fault段错误求助

问题相关代码
#include <stdio.h>
#include <stdlib.h>

typedef struct node
{
   int number;
   struct node *left;
   struct node *right;
}
node;

void print_tree(node *root);
void free_tree(node *root);

int main(void)
{
   node *tree = NULL;

   node *n = malloc(sizeof(node));
   if (n == NULL)
   {
       return 1;
   }

   // root
   n->number = 2;
   n->left = NULL;
   n->right = NULL;

   tree = n;

   n = malloc(sizeof(node));
   if (n == NULL)
   {
       free_tree(tree);
       return 1;
   }

   n->number = 1;
   n->left = NULL;
   n->right = NULL;

   tree->left = n;

   n = malloc(sizeof(node));
   if (n == NULL)
   {
       free_tree(tree);
       return 1;
   }

   n->number = 3;
   n->left = NULL;
   n->right = NULL;

   tree->right = n;

   print_tree(tree);
   free_tree(tree);
   return 0;
}

void print_tree(node* root)
{
   if (root == NULL)
   {
       return;
   }
   print_tree(root->left);
   printf("%i\n", root->number);
   print_tree(root->right);
}

void free_tree(node* root)
{
   if (root == NULL)
   {
       return;
   }
   free_tree(root->left);
   free_tree(root->right);
   free(root);
}
问题现象
  • 代码可正常完成二叉树中序遍历,按换行顺序输出1、2、3,符合预期
  • 程序运行结束前触发Segmentation fault段错误
  • 调试定位到错误触发位置为free_tree函数中的free_tree(root->left);语句
问题根源

你贴出的代码逻辑本身没有问题,正常编译运行不会触发段错误。出现该问题基本是以下三类原因导致,其中第一种概率最高:

  • 本地实际运行的代码中,free_tree的释放顺序错误
    如果本地代码把free(root);写在了两个递归调用之前,就会触发你遇到的问题:
    // 错误实现示例
    void free_tree(node* root)
    {
       if (root == NULL)
       {
           return;
       }
       free(root); // 提前释放当前节点内存,root成为野指针
       free_tree(root->left); // 访问已释放内存的left成员,直接触发段错误
       free_tree(root->right);
    }
    
    这种错误下,print_tree没有内存释放操作,遍历逻辑完全正常,可以正确输出1、2、3;但到内存释放阶段,先释放节点再访问节点的指针成员,属于典型的野指针访问,崩溃位置和你调试定位的位置完全吻合。
  • 堆内存被意外破坏
    常见触发场景:
    • malloc分配内存时大小写错,比如写成malloc(sizeof(node*)),只分配了指针长度的内存,远小于node结构体的实际大小。后续给节点的number、left、right成员赋值时会越界写入,破坏堆块的管理元数据。这类问题不会立刻崩溃,print阶段内存还未被回收,可能侥幸正常输出,但free阶段堆管理器校验元数据失败就会触发段错误。
    • 新malloc的节点漏写n->left = NULL; n->right = NULL;初始化,指针值为堆上的随机垃圾地址,递归遍历时访问到非法地址就会崩溃。这类问题大多在print阶段就会触发,概率相对较低。
  • 代码修改后未保存或未重新编译,运行的是旧版本的错误二进制文件,属于新手高频踩坑场景。
修复方案
  1. 严格按照后序遍历顺序实现free_tree:先递归释放左子树、再递归释放右子树、最后释放当前节点,也就是你贴出的写法,free(root);必须放在两个递归调用的最后。
  2. 检查所有malloc调用的内存大小,确保是sizeof(node)而非sizeof(node*);所有新创建的节点必须手动将left、right指针初始化为NULL,不要依赖malloc返回内存的默认值。
  3. 删除旧的编译产物,重新保存所有代码文件后完整编译再运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 18:54:24