一次vs code的无敌奇怪bug,局部地址修改在栈退出时未生效

493 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

[toc]

简介

日常敲代码,C语言在一次指针传参时,传入的一个局部变量地址在跳转到的函数中被修改了赋值,可是在函数返回后,该指针的赋值内容无缘无故依然是原先的默认值,一脸黑人问好,以下是当时的调试方法

问题介绍

  • 函数原型
    int anyfile(char* path, e_anyfile_types* type); 
    
  • 函数内容的最后两行
    ***
        *type = 1;
        return 0;
    }
    
  • 调用 main.c
    e_anyfile_types ftype = 0;
    
    int res = anyfile(path, &ftype);
    

ftype的默认值此时是0,在anyfile函数中的倒数第二行明确修改了为1,可是莫名其妙在main.c中,ftype执行完函数后依然是0

GDB调试查看

  • 先停到执行到函数前

    gdb test
    b main          // 停在入口
    r               // 启动
    n               // next step 一步一步走
    
  • 查看局部地址

    (gdb) p &ftype
    $2 = (e_anyfile_types *) 0x7fffffffe3ac
    
  • 断点

    (gdb) b *0x7fffffffe3ac
    Breakpoint 2 at 0x7fffffffe3ac
    
  • 当前我设置的所有断点

    (gdb) info b
    Num     Type           Disp Enb Address            What
    1       breakpoint     keep y   0x00000000004006e6 in main at test.c:12
            breakpoint already hit 1 time
    2       breakpoint     keep y   0x00007fffffffe3ac
    
  • 当我继续最终程序运行时,明确看到这里时执行到了并立即返回的,此时查看ftype的地址明确看到赋值是生效的

    ***
    *type = 1;
    return 0;
}

但当程序继续运行时,返回到mainftype并未被修改,断点也没有停止。。。。。。

排查

  • 检查makefile的编写,确认引用的函数是随着make重新生成的,调用的接口声明一致
  • 重新make

最后怎么解决的

  • 怀疑到了是不是枚举e_anyfile_types在函数内外的长度不一致导致的?重写粘贴赋值了这一行的枚举类型
    e_anyfile_types ftype = 0;
    

然后就好了。。。。。。

可是。。。。。。

[kira@localhost source]$ diff test.c  tt
20d19
<

可是这还是一摸一样的根本没有任何修改啊!!!!!!

一次奇怪的bug,还是不知道问题究竟在哪,奇怪的知识增加了。。。。。。

如果你也遇到了类似的问题

  • 排查其他问题
    • 确认函数的声明与调用一致一摸一样
    • 确认使用的静态库、动态库、头文件接口一致
    • 尤其是枚举类型,不同的编译方法可能导致枚举的长度不一致
    • 确认该局部变量的修改不会有其他地方干扰
    • 试试我这种奇葩思路,乱投医
  • 如果排查了所有可能还是不行,建议烧香拜佛,保佑bug远离我,我佛慈悲(真的)