C语言递归构建二叉树动态数组触发double free错误求助
问题分析与修复方案
核心错误:realloc的新地址无法同步回主函数
你的Sczytaj函数里,Drzewiec是按值传递的指针——函数内部的Drzewiec只是原指针的副本。当你调用realloc重新分配内存后,函数内的指针会指向新的内存块,但main里的原始Drzewiec指针还停留在旧地址上。而realloc在分配新内存时,通常会释放旧内存块,这就导致main里的指针变成了野指针。最后main调用free(Drzewiec)时,实际上是在释放一块已经被realloc回收的内存,自然触发了double free detected错误。
其他待修正的问题
- 内存扩容逻辑顺序颠倒:你先把
*c(数组容量)加2再调用realloc,但没有考虑当前索引是否真的需要扩容,逻辑不够严谨。 - 输出循环边界错误:用
wielkość(容量)作为循环上限,会输出数组中未初始化的内存区域,应该用实际存储元素的indeks作为边界。 - 冗余的指针写法:
&*a完全等价于a,没必要多此一举,直接传a即可。 - 缺少错误检查:没有检查
malloc和realloc的返回值,也没处理scanf的输入错误,容易导致程序崩溃。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> void Sczytaj(int** Drzewiec, int* a, int* b, int* c) { int Obecny, oindeks; // 检查输入是否有效 if (scanf("%d", &Obecny) != 1) { fprintf(stderr, "输入无效,请输入整数\n"); return; } oindeks = *a; // 先判断是否需要扩容:当前索引已达到或超过数组容量时扩容 if (oindeks >= *c) { *c += 2; // 按你的逻辑每次扩容2个元素,也可以改成翻倍更高效 int* new_ptr = realloc(*Drzewiec, sizeof(int) * (size_t)*c); if (!new_ptr) { fprintf(stderr, "内存分配失败\n"); exit(EXIT_FAILURE); } *Drzewiec = new_ptr; // 更新主函数中的原始指针 } (*Drzewiec)[oindeks] = Obecny; if (Obecny == 0) { *a += 1; return; } // 处理非空节点,递归读取左右子树 *a += 1; *b += 1; Sczytaj(Drzewiec, a, b, c); Sczytaj(Drzewiec, a, b, c); } int main(void) { printf("请输入数据(每行一个整数,0代表空节点):\n"); int wielkość = 1, indeks = 0, indeks_bez_zera = 0; int* Drzewiec = malloc(sizeof(int) * (size_t)wielkość); if (!Drzewiec) { fprintf(stderr, "初始内存分配失败\n"); return EXIT_FAILURE; } Sczytaj(&Drzewiec, &indeks, &indeks_bez_zera, &wielkość); printf("\n存储的二叉树数据:\n"); for (int i = 0; i < indeks; i++) { printf("%d\n", Drzewiec[i]); } printf("\n最后使用的索引:%d\n非空节点数量:%d\n数组当前容量:%d\n", indeks, indeks_bez_zera, wielkość); free(Drzewiec); return EXIT_SUCCESS; }
关键修复点说明
- 传递指针的指针:把函数参数改成
int** Drzewiec,调用时传&Drzewiec,这样函数内部可以直接修改主函数里的指针变量,确保所有递归调用和主函数都使用最新的内存地址。 - 修正扩容逻辑:先检查当前索引是否超出数组容量,再进行扩容,避免不必要的内存操作。
- 错误处理增强:添加了
malloc、realloc和scanf的错误检查,让程序更健壮。 - 输出逻辑修正:用
indeks(实际存储的元素个数)作为循环上限,避免输出未初始化的垃圾值。
测试示例
输入:
1 0 0
输出:
请输入数据(每行一个整数,0代表空节点): 1 0 0 存储的二叉树数据: 1 0 0 最后使用的索引:3 非空节点数量:1 数组当前容量:3
此时程序不会触发double free错误,运行完全正常。
内容的提问来源于stack exchange,提问作者Kiro99
相关产品推荐
相关产品推荐

