C++实现Trie类编写析构函数触发std::bad_alloc错误如何解决
问题原因
导致std::bad_alloc的核心原因有两个:
- clear函数参数使用值传递,造成无意义内存拷贝+野指针访问/双重释放
你的clear函数参数定义为unordered_map<char, Trie*> map,每次调用都会完整拷贝传入的map,平白产生大量不必要的内存分配。更严重的是逻辑冲突:
你手动在clear里递归调用clear处理子节点map、delete子节点的同时,delete操作会自动触发子对象的析构函数,而析构函数又会调用clear处理子对象自己的map。这时候子对象map里存的指针对应的内存已经被释放过,成为野指针——野指针不会被判断为nullptr,程序会继续对野指针指向的非法内存做递归clear、拷贝map、delete操作,要么触发无限递归持续申请内存直到耗尽,要么访问非法内存,最终抛出std::bad_alloc。 - 递归释放逻辑重复冗余
你不需要手动递归调用clear处理子节点的map:当你delete一个子Trie节点时,该节点的析构函数会自动执行,遍历它自己的map删除下一级节点,天然就会完成递归释放的流程,你额外写的递归调用完全多余,直接导致了上面说的重复释放问题。
修复方案
两种改法选其一即可:
改法1:简化析构逻辑,去掉冗余的clear递归
不需要单独实现clear函数,直接在析构函数里遍历当前节点的map,逐个delete子节点就够了,delete会自动触发子节点的析构完成递归释放:
~Trie() { for (auto& pair : map) { delete pair.second; } map.clear(); }
直接删掉原来写的clear成员函数即可,逻辑最简单,不会出问题。
改法2:保留clear函数,修正参数传递+去掉重复递归
如果要单独抽clear函数做清理,首先把参数改成左值引用避免拷贝,其次去掉手动递归调用clear的逻辑(delete会自动触发析构递归):
~Trie() { clear(map); } // 注意参数加&,使用引用传递,避免拷贝 void clear(unordered_map<char, Trie*>& map) { for (auto& pair : map) { // delete自动触发子节点析构,子节点会自行清理内部的map delete pair.second; } map.clear(); }
额外注意
你最开始写的类定义有基础语法错误:类定义结尾必须加分号,class myClass { ... }; 末尾的分号不能遗漏,否则会触发编译错误。
内容的提问来源于stack exchange,提问作者artisan1218
相关产品推荐
相关产品推荐

