std::map 自定義key型別,重寫operator<() 沒有嚴格弱序引起的“invalid comparator”

GlLamant發表於2020-10-12


問題

現象

生產環境中偶發崩潰,除錯時彈出以下彈窗:
在這裡插入圖片描述
定位問題為 map自定義key型別重寫operator<() 沒有嚴格弱序引起。

特徵

  1. 編譯正常,執行時偶發(取決於key值),容易讓人以為是指標問題。

問題分析

嚴格弱序三要求

參考自: C++ 嚴格弱序

  1. 兩個關鍵字不能同時“嚴格弱序”於對方
  2. 如果a“嚴格弱序”於b,且b“嚴格弱序”於c,則a必須“嚴格弱序”於c
  3. 如果存在兩個關鍵字,任何一個都不“嚴格弱序”於另一個,則這兩個關鍵字是相等的。

測試demo

  1. 根據業務程式碼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
    		// 嚴格弱序
    		return account < right.account && type < right.type;
    #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;
    }
    
  2. 參考 C++ 嚴格弱序的做法,定義以下三個變數:
    StKey a(0, 2);
    StKey b(1, 0);
    StKey c(0, 1);
    
    嚴格弱序三要求第二條結果如下:
非嚴格弱序嚴格弱序
a < btruefalse
b < ctruefalse
a < cfalsefalse

相關文章