一行简单的 C++字符串处理代码引发的血案 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
vfx666
V2EX    程序员

一行简单的 C++字符串处理代码引发的血案

  •  
      vfx666 323 天前 1658 次点击
    这是一个创建于 323 天前的主题,其中的信息可能已经有所发展或是发生改变。
    原谅我标题党……
    但这个事确实很蹊跷。起初是客户反映程序在几小时后会闪退,调试了很久,终于定位到问题
    xid.erase(xid.end() - 2, xid.end());
    ( xid 是 std string 类型的全局变量)
    就这么一行简单的代码,会导致程序在正常运行几小时后触发崩溃。即使该行代码并没有执行(并且这行代码也不会触发崩溃),但只要编译时有这行代码,程序刚开始一切正常,过了几小时后必崩。删了这行重新编译就一切正常。
    不知道各位大佬怎么看……难不成是编译器的 bug ?
    13 条回复    2024-11-26 19:22:25 +08:00
    bfjm
        1
    bfjm  
       323 天前 via iPhone
    xid 大小是否超过了 2 xid 是否有线程安全问题
    vfx666
        2
    vfx666  
    OP
       323 天前 via iPhone
    @bfjm 都没有
    bfjm
        3
    bfjm  
       323 天前
    @vfx666 用 valgrind 跑一下 可以把堆栈信息贴出来
    billccn
        4
    billccn  
       323 天前
    你是怎么定位到这行代码的?

    这代码看上去人畜无害,除非编译器认为 xid.size()必定小于 2 ,于是编译了个 undefined behavior 进去?

    当然编译问题也是有可能的,你有保留这行代码然后 clean 编译过一次吗?
    vfx666
        5
    vfx666  
    OP
       322 天前 via iPhone
    @billccn 一点点排除定位到的问题,因为测试了软件之前的发行版没有问题,这就可以把范围缩小到具体的代码段了。然后进一步缩小排除,最后发现就是这么一行

    保留这行代码,即使此代码并没有被执行(写一个 if 判断故意跳过这行)还是会触发问题。你说的 clean 编译是指的那个“重新编译…”选项吗
    w568w
        6
    w568w  
       322 天前
    @vfx666 怎么“故意跳过”的? if(false)?

    说实话我觉得可能性更大的是定位错了问题位置。具体闪退有 dump 吗?有试过删除这行代码就好了吗?
    vfx666
        7
    vfx666  
    OP
       322 天前 via iPhone
    @w568w 就是试过,删了就好了。所以很离谱
    araraloren
        8
    araraloren  
       322 天前
    haha
    Promtheus
        9
    Promtheus  
       322 天前
    每个程序员都经历过这种看不出问题只能一个个代码删掉试试看的情况。哈哈哈 我在想是不是火箭飞船这些上面的代码也有这种情况
    realpg
        10
    realpg  
    PRO
       322 天前
    先改写这一行
    xid.erase(xid.end() - 2, xid.end());

    拆语句成

    tmp_a = xid.end()
    tmp_b = tmp_a -2
    log tmp_a, tmp_b to logfile with current timestamp
    xid.erase(tmp_b,tmp_a)
    lixile
        11
    lixile  
       322 天前
    大概率 overflow 了 只是这行代码所在参与编译后 导致崩溃的内存位置被 overflow 到了
    不参与时 overflow 位置 没有涉及关键内存
    billccn
        12
    billccn  
       322 天前
    @vfx666 等等,一楼问你 xid 大小有没有超过 2 ,你二楼回答没有。那 xid 的大小会不会不到 2 ?你加的 if 是检测 xid 的长度吗?不是的话能不能加一个试试?可能其他部分就有 bug ,导致 xid 偶尔不到 2 个长,之前没有做 erase 所以没有发现?

    然后,11 楼说的是很有可能的,因为你这行代码虽然不执行,但是为了能执行这行代码,编译器可能改变了堆栈帧的长度,或者初始化了某些信息,这导致其他(已有的)代码 overflow 到了更关键的地方。

    但我们这都是凭空猜测,你要想方设法弄到个 stack 。
    vfx666
        13
    vfx666  
    OP
       322 天前 via iPhone
    @lixile 这行代码改为
    xid = xid.substr(0, xid.size() - 2);
    程序就一切正常了。。。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1007 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 18:48 PVG 02:48 LAX 11:48 JFK 14:48
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86