You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86-64 GCC 13.1下C++异常:编译器判定if条件恒为真

编译器判定条件恒为真的原因分析

问题现象

  • 两段逻辑看似等价的代码出现截然不同的运行结果:
    • 使用if(0 <= start)(其中start = j - wordDict[i].size() + 1)时,代码运行正常
    • 直接使用if(0 <= j - wordDict[i].size() + 1)时,程序抛出错误:"basic_string::substr: __pos (which is 18446744073709551613) > this->size() (which is 8)"
  • 查看汇编代码发现,编译器认为后者的if条件恒为真,不会执行跳转分支,导致后续substr调用传入非法参数触发越界。

核心原因

这是C++隐式类型转换导致的无符号整数溢出问题:

  • wordDict[i].size()返回的是size_t类型(无符号整数),而循环变量j是int类型(有符号整数)
  • 执行j - wordDict[i].size() + 1时,C++会将j隐式转换为size_t类型参与运算
  • 当wordDict[i].size() > j + 1时,无符号整数的溢出绕回规则会让运算结果变成一个极大的正整数(比如报错中的18446744073709551613)
  • 无符号整数与0比较时,0 <= 极大无符号数永远为真,因此编译器会优化掉分支判断,直接执行后续代码,最终触发substr越界错误

而使用int start = ...的写法时,运算结果会被强制转换为int(有符号整数),此时负数值会被正确保留,0 <= start会判断为假,跳过危险分支。

修复方案

  • 方案1:显式将size()结果转为有符号整数:
    if (0 <= j - static_cast<int>(wordDict[i].size()) + 1)
    
  • 方案2:保留先计算start再判断的写法(原正常逻辑)
  • 方案3:调整比较逻辑,避免无符号溢出:
    if (j + 1 >= wordDict[i].size())
    
    此写法中j会被转为size_t,但逻辑等价且不会出现溢出绕回的问题

修复后的完整代码示例

#include <string>
#include <vector>
#include <unordered_set>
using namespace std;
bool wordBreak(string s, vector<string>& wordDict) {

    vector<bool> dp(s.size(), false);
    unordered_set<string> all(wordDict.begin(), wordDict.end());

    for (int j = 0; j < s.size(); j++)
    {
        for (int i = 0; i < wordDict.size(); i++)
        {
            int len = static_cast<int>(wordDict[i].size());
            int start = j - len + 1;
            if (0 <= start)
            {
                string word = s.substr(start, len);
                if (all.find(word) != all.end() && (start == 0 || dp[j - len]))
                {
                    dp[j] = true;
                }
            }
        }
    }
    return dp[s.size()-1];
}

int main(int args, char * argv[])
{
    string s = "leetcode";
    vector<string> wordDict = {"leet","code"};
    wordBreak (s, wordDict);
    return 0;
}

内容的提问来源于stack exchange,提问作者Cyokeo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 18:54:50