LeetCode findAnagrams提交报unsigned offset溢出错误排查求助
问题根源分析
- 核心问题是无符号整数隐式转换导致的字符串下标越界:
std::string::size()返回的是无符号类型size_t,当你用int类型的1+i和它做减法运算时,int会被隐式转换为无符号类型,运算结果也会是无符号类型。 - 当
1+i < p.size()时,1+i - p.size()的数学结果为负数,转换为无符号类型后会变成极大的正整数,此时你写的1+i - p.size() >= 0判断永远为真,程序会用这个非法的超大下标去访问s字符串,触发内存越界,和你看到的报错完全吻合。 - 本地运行正常是因为默认编译选项没有开启
UndefinedBehaviorSanitizer(UBSan)检查,越界访问的内存刚好没有触发段错误,属于未定义行为的随机表现,不代表代码本身没有问题。
复现方法
- 构造最简单的触发用例:
s = "a", p = "ab",此时p长度大于s长度,运行代码必然触发越界;所有s长度小于p长度的用例都可以稳定复现该问题。 - 本地复现需要在编译时加上UBSan检查参数:
g++ -fsanitize=undefined -o test test.cpp,运行编译后的程序就会弹出和LeetCode完全一致的报错。
修复方案
提前把p的长度转换为有符号int类型存储,避免隐式无符号转换即可:
bool find_match(const std::map<char, std::pair<int, int>> &m){ for(const auto& [k, v] : m){ if(v.first != v.second) return false; } return true; } std::vector<int> findAnagrams(std::string s, std::string p){ std::vector<int> result; int p_len = static_cast<int>(p.size()); // 提前加边界判断,s比p短直接返回空 if (static_cast<int>(s.size()) < p_len) return result; std::map<char, std::pair<int, int>> search; for(const char& c : p){ search[c].first++; search[c].second = 0; } for(int i = 0; i < s.size(); i++){ if(p.find(s[i]) != p.npos) search[s[i]].second++; if(find_match(search)) result.push_back(1 + i - p_len); int left = 1 + i - p_len; if(left >= 0 && p.find(s[left]) != p.npos) search[s[left]].second--; } return result; }
内容的提问来源于stack exchange,提问作者ianwt
相关产品推荐
相关产品推荐

