使用自定义比较器的std::set触发程序崩溃问题排查
问题分析与修复
错误原因
- 自定义比较器空指针崩溃:原代码用函数指针
decltype(cmp)*作为std::set的比较器类型,但通过bucketCuisines[cuisines[i]]创建新集合时,默认构造的set会使用空指针作为比较器。插入元素时调用空指针,直接触发崩溃(DEADLYSIGNAL)。 - 评分更新逻辑错误:
changeRating函数中,插入新条目时误用了旧评分oldRating,而非新评分newRating,导致结果不符合预期。
修复方案
1. 替换函数指针为仿结构体比较器
使用重载operator()的结构体作为比较器,std::set默认构造时会自动生成合法的比较器实例,彻底避免空指针调用问题。
2. 修正评分更新的插入参数
将插入操作的oldRating改为newRating,确保更新后的评分正确存入集合。
修复后的完整代码
class FoodRatings { public: struct Cmp { bool operator()(const pair<int, string>& a, const pair<int, string>& b) const { if (a.first == b.first) return a.second < b.second; return a.first > b.first; } }; unordered_map<string, int> bucketFoods; unordered_map<string, string> bucketFoodNCuisine; map<string, set<pair<int, string>, Cmp>> bucketCuisines; FoodRatings(vector<string>& foods, vector<string>& cuisines, vector<int>& ratings) { int n = foods.size(); for (int i = 0; i < n; ++i) { bucketFoods[foods[i]] = ratings[i]; bucketFoodNCuisine[foods[i]] = cuisines[i]; bucketCuisines[cuisines[i]].insert({ratings[i], foods[i]}); } } void changeRating(string food, int newRating) { int oldRating = bucketFoods[food]; bucketFoods[food] = newRating; string cuisine = bucketFoodNCuisine[food]; bucketCuisines[cuisine].erase({oldRating, food}); bucketCuisines[cuisine].insert({newRating, food}); } string highestRated(string cuisine) { return bucketCuisines[cuisine].begin()->second; } };
验证结果
针对给定输入:
["FoodRatings","highestRated","highestRated","changeRating","highestRated","changeRating","highestRated"] [[["kimchi","miso","sushi","moussaka","ramen","bulgogi"],["korean","japanese","japanese","greek","japanese","korean"],[9,12,8,15,14,7]],["korean"],["japanese"],["sushi",16],["japanese"],["ramen",16],["japanese"]]
修复后的代码输出与预期完全一致:
[null, "kimchi", "ramen", null, "sushi", null, "ramen"]
内容的提问来源于stack exchange,提问作者Eunno An
相关产品推荐
相关产品推荐

