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

C语言二叉树镜像实现中访问已初始化左节点指针触发SIGSEGV

问题背景

编写返回二叉树镜像副本的函数,镜像规则为树中每个节点的左子节点与右子节点互换位置。
练习提供的可视化示例
左侧原树经复制后生成右侧的镜像树,初始实现的二叉树节点定义、镜像生成函数、节点插入函数C语言代码如下:

typedef struct bNode {
    int data;
    struct bNode *left;
    struct bNode *right;
} bNode;
    
//  =============================================================
    
bNode* reverse_tree (bNode **tree) {
    bNode *copy = malloc(sizeof(bNode));
    copy->data = (*tree)->data;
    if (!((*tree)->right) && !((*tree)->left)){
        return copy;
    }
        
    copy->left = reverse_tree(&(*tree)->right);
    copy->right = reverse_tree(&(*tree)->left);
    return copy;
}
    
//  =============================================================
    
void insert(bNode **tree, int data) {
    bNode *temp, *previous, *current;

    if (*tree == NULL) {
        temp = (bNode *) malloc(sizeof (bNode));
        temp->data = data;
        temp->left = NULL;
        temp->right = NULL;
        *tree = temp;
        return;
    }

    if (data < (*tree)->data) {
        insert(&(*tree)->left, data);
    } else if (data > (*tree)->data) {
        insert(&(*tree)->right, data);
    }
}

测试发现单层递归可正常运行,递归深度超过一层后指针失效,指向不可访问内存,程序触发SIGSEGV段错误。

SIGSEGV触发原因
  • 递归终止逻辑存在漏洞:当前终止判断仅在节点同时没有左、右子节点(即叶子节点)时触发,一旦节点仅存在单侧子节点,判断条件不成立,代码会继续对不存在的另一侧NULL子节点发起递归调用。递归进入下一层后,第一行代码就会执行copy->data = (*tree)->data,此时*tree为NULL,对空指针解引用直接访问非法内存,触发段错误。
  • 新建副本节点未初始化指针:叶子节点分支返回的copy节点没有对left、right成员赋值,这两个指针为随机野值,后续遍历镜像树时同样会触发内存访问错误。
修复方案
  • 将空节点判断提前到函数入口作为递归终止条件:如果传入的节点指针为NULL,直接返回NULL,无需分配内存,从根源上避免空指针解引用。
  • 新分配的节点结构体显式初始化所有指针成员,避免野指针。
  • 移除原有的叶子节点特殊判断,所有非空节点统一完成复制、递归交换子节点的逻辑即可。

修正后的reverse_tree实现如下:

bNode* reverse_tree (bNode **tree) {
    // 递归终止:空节点直接返回NULL
    if (*tree == NULL) {
        return NULL;
    }
    // 分配当前节点副本并初始化所有成员
    bNode *copy = malloc(sizeof(bNode));
    copy->data = (*tree)->data;
    copy->left = NULL;
    copy->right = NULL;
    // 递归镜像复制子节点:原右子树放到新树左节点,原左子树放到新树右节点
    copy->left = reverse_tree(&(*tree)->right);
    copy->right = reverse_tree(&(*tree)->left);
    return copy;
}

注:C语言中malloc分配的内存内容是未定义的,只要结构体包含指针成员,分配后必须手动初始化,不能依赖内存默认值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 13:15:41