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
相关产品推荐
相关产品推荐

