使用bits/stl_tree.h存储自定义类型指针时出现segmentation fault问题
问题原因
- 首先
std::_Rb_tree是GCC libstdc的私有内部实现,不属于C标准公开接口,其内部逻辑、参数约束、方法行为都没有任何公开兼容性保证,直接使用本身就是不符合规范的做法。 - 你当前触发段错误的直接原因是GCC 8.3.1版本的
_Rb_tree内部插入逻辑中,存在直接比较「键类型」和「存储值类型」的分支,不会每次都主动调用KeyOfValue把值转换为键再比较。你传入的比较器是std::less<double>,仅支持两个double值的比较,当内部把存储的my_type*指针直接传给比较器时,会发生非法类型转换:要么把指针地址当成double值解析,要么把double键值当成指针地址访问内存,最终触发段错误。
修复方案
方案1(推荐):使用标准库公开容器
完全不需要触碰私有内部接口,用标准库std::multimap即可满足你的需求,接口稳定且无兼容风险:
#include <map> struct my_type { double key; uint64_t data; my_type(double _key, uint64_t _data) : key(_key), data(_data) {} my_type(const my_type&) = delete; }; int main() { std::multimap<double, my_type*> my_tree; auto e0 = new my_type(100.0, 100); auto e1 = new my_type(101.0, 101); my_tree.insert({e0->key, e0}); my_tree.insert({e1->key, e1}); // 后续遍历、查找、删除逻辑均符合标准规范 }
方案2(不推荐,仅适配当前版本_Rb_tree)
如果必须使用_Rb_tree,需要调整模板参数和仿函数,让比较器支持键、值的混合比较:
#include <bits/stl_tree.h> struct my_type { double key; uint64_t data; my_type(double _key, uint64_t _data) : key(_key), data(_data) {} my_type(const my_type&) = delete; }; // 键提取器直接返回存储的指针 struct key_of_value { constexpr const my_type* operator()(const my_type* p) const noexcept { return p; } }; // 比较器支持double和my_type*的全组合比较 struct my_type_cmp { bool operator()(double a, const my_type* b) const noexcept { return a < b->key; } bool operator()(const my_type* a, double b) const noexcept { return a->key < b; } bool operator()(const my_type* a, const my_type* b) const noexcept { return a->key < b->key; } }; int main() { // 调整模板参数,键类型和值类型均为my_type* std::_Rb_tree<const my_type*, my_type*, key_of_value, my_type_cmp> my_tree; auto e0 = new my_type(100.0, 100); auto e1 = new my_type(101.0, 101); my_tree._M_insert_equal(e0); my_tree._M_insert_equal(e1); }
内容的提问来源于stack exchange,提问作者cynric4sure
相关产品推荐
相关产品推荐

