使用自定义比较器的C++ STL Map访问值时触发段错误
问题分析与解决:STL map自定义比较器引发段错误
问题描述
使用C++ STL的map容器,键值对均为自定义star::Node类的指针。可正常存储数据和遍历所有键值对,但通过键访问对应值的成员变量时,触发「Segmentation fault (core dumped)」运行时错误。移除自定义比较器NodeCostPointer后错误消失,问题确认源于该比较器。
相关代码
主程序代码
#include <iostream> #include <map> #include <Eigen/Dense> #include <vector> #include "A_star.h" using namespace std; struct NodeCostPointer { bool operator()(star::Node* const& a,star::Node* const& b){ return a->f_cost >= b->f_cost; // 注:此处缺失闭合大括号,属于语法错误 } // 需要补充这个大括号 int main() { Eigen::Matrix<float,3,3> obj; obj(0,0) = 3360; obj(1,0) = 3360; obj(2,0) = 3360; obj(0,1) = 7000; obj(1,1) = 7000; obj(2,1) = 7000; obj(0,2) = 5280; obj(1,2) = 5280; obj(2,2) = 5280; Eigen::Matrix<float,3,1> end; end(0) = 12300; end(1) = 12300; end(2) = 12300; Eigen::Matrix<float,3,1> start; start(0) = -.8; start(1) = -.8; start(2) = -.8; map<star::Node*,star::Node*, NodeCostPointer> test; star::Node* nodetest = new star::Node(start,6,0); star::Node* nodetest2 = new star::Node(end,6,0); star::Node* nodetest3 = new star::Node(start,5,std::numeric_limits<float>::infinity()); test[nodetest] = nodetest3; test[nodetest2] = nodetest3; // 错误触发点 cout << test[nodetest]->f_cost << endl; // 或 test[nodetest]->f_cost = 4; map<star::Node*,star::Node*,NodeCostPointer>::iterator itt; for(itt=test.begin();itt!=test.end();itt++){ cout << itt->first->cordinates << endl; cout << " \n"; } return 0; }
Node类构造函数实现
star::Node::Node(Eigen::Matrix<float,3,1> _cordinates, float _h_cost, float _g_cost) : cordinates {_cordinates}, h_cost {_h_cost}, g_cost {_g_cost}{ f_cost = h_cost+g_cost; obstical = false; closedNode = false; };
错误原因
- 比较器违反严格弱序规则
STLmap依赖红黑树实现,要求自定义比较器必须满足严格弱序,核心规则包括:- 对于任意元素
a,comp(a,a)必须返回false(自反性) - 若
comp(a,b)为true,则comp(b,a)必须为false(非对称性)
- 对于任意元素
你的比较器使用return a->f_cost >= b->f_cost,当a和b指向的Node的f_cost相等时,comp(a,a)返回true,直接违反自反性,导致红黑树结构混乱。后续用test[nodetest]查找键时,混乱的树结构会引发非法内存访问,触发段错误。
比较逻辑不符合键的唯一性需求
如果两个不同的Node*指针指向的Node对象f_cost相同,你的比较器会认为这两个键相等,导致map无法正确区分不同的指针键,进一步破坏内部结构。语法错误
NodeCostPointer结构体的operator()函数缺失闭合大括号,属于语法错误,可能导致编译器解析异常,加剧问题。
解决方案
方案1:修复自定义比较器(保留排序需求)
如果需要map按Node的f_cost降序排列,同时保证不同指针即使f_cost相同也能被视为不同键,修复比较器如下:
struct NodeCostPointer { bool operator()(star::Node* const& a, star::Node* const& b) { // 先按f_cost降序(用>保证严格弱序) if (a->f_cost != b->f_cost) { return a->f_cost > b->f_cost; } // f_cost相同时,比较指针地址,确保不同指针被正确区分 return a < b; } };
方案2:移除自定义比较器(无需排序)
如果不需要按f_cost排序,直接使用默认的指针比较(按内存地址)即可,默认比较器天然满足严格弱序,移除后map可正常工作。
内容的提问来源于stack exchange,提问作者mpesson
相关产品推荐
相关产品推荐

