问题
现象
生产环境中偶发崩溃,调试时弹出以下弹窗:
定位问题为 map自定义key类型重写operator<() 没有严格弱序引起。
特征
- 编译正常,运行时偶发(取决于key值),容易让人以为是指针问题。
问题分析
严格弱序三要求
参考自: C++ 严格弱序
- 两个关键字不能同时“严格弱序”于对方
- 如果a“严格弱序”于b,且b“严格弱序”于c,则a必须“严格弱序”于c
- 如果存在两个关键字,任何一个都不“严格弱序”于另一个,则这两个关键字是相等的。
测试demo
-
根据业务代码bug输出demo如下:
#include <map> struct StKey { int account; int type; StKey(int account_, int type_): account(account_), type(type_) { } bool operator<(const StKey & right) const { #if 1 // 严格弱序 if (account != right.account) { return account < right.account; } if (type != right.type ) { return type < right.type ; } return false; #else // 非严格弱序,产生的原来实现 return account < right.account ? true : type < right.type ? true : false; #endif } }; int main() { std::map<StKey, std::string> partMap; partMap[StKey(0, 1)] = "connection_2"; StKey partKey(1, 0); if (partMap.count(partKey)) { partMap[partKey] = "connection_3-1"; } return 0; }
-
参考 C++ 严格弱序的做法,定义以下三个变量:
StKey a(0, 2); StKey b(1, 0); StKey c(0, 1);
则 严格弱序三要求 第二条结果如下:
operator<() 非严格弱序 严格弱序 a < b true false b < c true false a < c false false -
两种实现的区别
- 上述非严格弱序实现中,如果a/b之间以account判断是否小于,b/c之间以type判断是否小于,a < c 并不是恒成立。
- 严格弱序的实现是要求比较。
- 上述非严格弱序实现中,如果a/b之间以account判断是否小于,b/c之间以type判断是否小于,a < c 并不是恒成立。