V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
vfx666
V2EX  ›  程序员

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

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

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

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

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

    说实话我觉得可能性更大的是定位错了问题位置。具体闪退有 dump 吗?有试过删除这行代码就好了吗?
    vfx666
        7
    vfx666  
    OP
       9 天前 via iPhone
    @w568w 就是试过,删了就好了。所以很离谱
    araraloren
        8
    araraloren  
       9 天前
    haha
    Promtheus
        9
    Promtheus  
       9 天前
    每个程序员都经历过这种看不出问题只能一个个代码删掉试试看的情况。哈哈哈 我在想是不是火箭飞船这些上面的代码也有这种情况
    realpg
        10
    realpg  
       8 天前
    先改写这一行
    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  
       8 天前
    大概率 overflow 了 只是这行代码所在参与编译后 导致崩溃的内存位置被 overflow 到了
    不参与时 overflow 位置 没有涉及关键内存
    billccn
        12
    billccn  
       8 天前
    @vfx666 等等,一楼问你 xid 大小有没有超过 2 ,你二楼回答没有。那 xid 的大小会不会不到 2 ?你加的 if 是检测 xid 的长度吗?不是的话能不能加一个试试?可能其他部分就有 bug ,导致 xid 偶尔不到 2 个长,之前没有做 erase 所以没有发现?

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

    但我们这都是凭空猜测,你要想方设法弄到个 stack 。
    vfx666
        13
    vfx666  
    OP
       8 天前 via iPhone
    @lixile 这行代码改为
    xid = xid.substr(0, xid.size() - 2);
    程序就一切正常了。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3552 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 04:33 · PVG 12:33 · LAX 20:33 · JFK 23:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.