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

请教各位老哥, Windows 下 Release 程序崩溃,应该如何定位问题?

  •  
  •   liuguangxuan · 2023-12-26 08:12:38 +08:00 · 3438 次点击
    这是一个创建于 370 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景

    在有开发环境的机器上,可以调试启动代码,复现问题后,很容易就能定位到问题代码。

    但是往往给用户的程序是 Release 版本的 exe ,崩溃后,可能会产生一个 dmp 文件。

    问题

    1. 这个 dmp 文件是 Release 版本 exe 产生的,如何根据这个 dmp 定位到问题代码?
    2. 如果不能根据这个 dmp 文件定位到问题代码,那么是否有其他方式,定位问题代码?
    3. 是否有定位问题,调试 bug 的其他技巧?
    4. 关于调试符号( pdb 文件),了解到有符号服务器,可以专门存储符号文件,是否有相关的最佳实践?如何编译,打包,发布,存储符号,调试定位问题?
    55 条回复    2024-08-15 19:15:26 +08:00
    snailya
        1
    snailya  
       2023-12-26 08:20:08 +08:00
    我不会,我就知道打印日志。
    ysc3839
        2
    ysc3839  
       2023-12-26 08:20:50 +08:00 via Android   ❤️ 1
    用 Visual Studio 打开 dmp 文件
    liuguangxuan
        3
    liuguangxuan  
    OP
       2023-12-26 08:24:10 +08:00
    @ysc3839 #2 这个 dmp 文件是 Release 版本产生的,能看到堆栈信息吗?
    corcre
        4
    corcre  
       2023-12-26 08:34:41 +08:00   ❤️ 1
    打印日志+1
    实在不行让客户给个权限, 你丢个 debug 版本的过去远程调试一下
    StubbornHuang
        5
    StubbornHuang  
       2023-12-26 08:38:49 +08:00   ❤️ 1
    日志大法 解决问题
    ysc3839
        6
    ysc3839  
       2023-12-26 08:40:36 +08:00 via Android
    liaixiao
        7
    liaixiao  
       2023-12-26 08:44:24 +08:00 via iPhone   ❤️ 1
    打印日志 or ,查看 windows 的日志,windows 管理有一个日志功能,会记录程序异常退出的日志。最保险的办法还是自己打印日志
    DTCPSS
        8
    DTCPSS  
       2023-12-26 08:44:49 +08:00   ❤️ 2
    Windbg
    nevermoreluo
        9
    nevermoreluo  
       2023-12-26 08:46:01 +08:00
    排除 release 编译环境问题,dmp 没法定位到问题代码,就开对应的参数 例如 zi ,降低优化之类的,注意自己到底是 mingw 还是 msvc ,两者不一样,去找下对应的编译器怎么让 dmp 文件有符号链接。
    感觉大概率是什么两边配置对不上。
    vs 的话就仔细对比 vcproject 文件,两个环境有啥区别,cmake 注意不要关掉 return 空的警告(曾经在某个 gcc 版本上遇到没写 return debug 好的,release 崩了的情况)

    最后实在不行,你永远可以相信打印日志。。。先把作业做了,后面有空再折腾 release 的 dump 文件如何获取堆栈问题
    gbw1992
        10
    gbw1992  
       2023-12-26 08:47:40 +08:00   ❤️ 1
    gleArk
        11
    gleArk  
       2023-12-26 09:12:08 +08:00   ❤️ 1
    会汇编语言吗,x32dbg/x64dbg 反编译,跟踪到崩溃前最后一行汇编码,然后分析这一行代码具体执行了什么
    不需要源代码
    GreyWang
        12
    GreyWang  
       2023-12-26 09:15:20 +08:00   ❤️ 1
    dmp 文件已经包含了出问题时的堆栈信息,你可以用 Windows 自己生成的 dmp 文件,也可以利用 crash_handler 自己生成 dmp 文件。

    如果 release 程序是用 Visual Studio 编译的:
    1 、打开这个程序的解决方案文件
    2 、直接把 dmp 文件拖进去 VS 打开
    3 、设置符号目录、包含编译 release 程序时的 pdb 文件,或者动态库文件(如果有自己生成库的话)
    4 、点击本地调试、直接跳转到崩溃时的堆栈代码帧
    capella
        13
    capella  
       2023-12-26 09:16:51 +08:00   ❤️ 1
    系统里的应用日志
    sinx003
        14
    sinx003  
       2023-12-26 09:25:06 +08:00   ❤️ 1
    你是用的 vs studio 开发吧,如果你能复现,可以在 release 模式下,实现 debug 下的打断点。
    参考: https://blog.csdn.net/qq_36333986/article/details/103897038
    sloknyyz
        15
    sloknyyz  
       2023-12-26 09:30:15 +08:00
    用 visual studio 打开 dump ,加载 pdb ,会自动分析并显示崩溃堆栈,这是最简单方便的。
    tool2d
        16
    tool2d  
       2023-12-26 09:44:30 +08:00
    @nevermoreluo mingw 现在和以前不一样,只要配置一下,就可以生成 vc 能识别 codeview 调试信息。

    也就是说,vc 能直接调试任何 exe 代码了。
    zoe0316
        17
    zoe0316  
       2023-12-26 09:48:52 +08:00   ❤️ 1
    也可以试试集成 Breakpad 到项目里,根据 pdb 生成符号表,crash 的时候再解析 dmp 。

    https://github.com/google/breakpad
    proxytoworld
        18
    proxytoworld  
       2023-12-26 10:05:25 +08:00
    release 的 dmp 你载入生成的 pdb 不就行了、
    z4none
        19
    z4none  
       2023-12-26 10:30:16 +08:00   ❤️ 1
    使用 dmp 定位问题应该是最方便的,
    pdb 文件可以用 symstore 工具管理,
    保存了 pdb 文件后,通过配置环境变量 _NT_SYMBOL_PATH 就能让 vs 找到 dmp 相应版本的 pdb 文件
    695975931
        20
    695975931  
       2023-12-26 10:35:14 +08:00   ❤️ 1
    给你推荐一个大佬公众号:一线码农聊技术,底下有他的联系方式。
    apie
        21
    apie  
       2023-12-26 11:04:16 +08:00   ❤️ 1
    ReleaseWithDebugInfo
    shuax
        22
    shuax  
       2023-12-26 11:12:37 +08:00
    我会 x64dbg 和 ida 配合使用。
    pzpr
        23
    pzpr  
       2023-12-26 11:20:09 +08:00   ❤️ 1
    我一般用 windbg 分析 dump ,通过崩溃线程和变量值定位到代码后自己复现,看到上面有老哥说 vs studio 也可以用,下次尝试下
    ashong
        24
    ashong  
       2023-12-26 11:27:29 +08:00 via iPhone   ❤️ 1
    @liuguangxuan 可以,如果你编译的时候生成 debug info , 记得保留好 pdb 以及源代码状态。

    用 vs 或者 windbg 都可定位
    402124773
        25
    402124773  
       2023-12-26 11:33:46 +08:00
    既然有 dump ,你自己又有 pdb ,那肯定是使用 windbg 啊。可以直接看到最后出错的 stack 。
    liuguangxuan
        26
    liuguangxuan  
    OP
       2023-12-26 13:09:36 +08:00
    @snailya #1 已经很厉害了。
    liuguangxuan
        27
    liuguangxuan  
    OP
       2023-12-26 13:12:54 +08:00
    @ashong #24 老哥可否细说一下”保留好 pdb 以及源代码状态“?
    pdb 我看楼下有提到了 symstore ,是这个吗?
    源代码状态,git 版本回退回来是否可以?
    liuguangxuan
        28
    liuguangxuan  
    OP
       2023-12-26 13:14:07 +08:00
    @corcre #4 就算客户给了权限,debug 版本依赖 mfc100ud.dll 、msvcp100d.dll 等各种后缀带 d 的动态库,也没办法直接运行 debug 版本的 exe 。
    liuguangxuan
        29
    liuguangxuan  
    OP
       2023-12-26 13:14:59 +08:00
    @StubbornHuang #5 如果是维护一个比较大型的旧项目,根本不知道在哪里加日志。😂
    liuguangxuan
        30
    liuguangxuan  
    OP
       2023-12-26 13:16:54 +08:00
    @nevermoreluo #9 #5 如果是维护一个比较大型的旧项目,根本不知道在哪里加日志。😂
    liuguangxuan
        31
    liuguangxuan  
    OP
       2023-12-26 13:18:47 +08:00
    @gleArk #11 老哥可否细说一下?反编译 exe ,还是 dmp ?如何查到崩溃前最后一行汇编码?查到了汇编码怎么定位问题代码?
    liuguangxuan
        32
    liuguangxuan  
    OP
       2023-12-26 13:22:29 +08:00
    @GreyWang #12 老哥,假如这个程序是由自动打包工具编译生成的,不是我生成的,而且我没有编译 release 程序时的 pdb 文件,那么怎么定位问题代码呢?
    liuguangxuan
        33
    liuguangxuan  
    OP
       2023-12-26 13:23:53 +08:00
    @sloknyyz #15 老哥,我没有 pdb ,exe 是自动打包工具编译生成的。这种情况下如何定位问题呢?
    liuguangxuan
        34
    liuguangxuan  
    OP
       2023-12-26 13:25:53 +08:00
    @zoe0316 #17 多谢老哥,我去了解一下这个工具。
    liuguangxuan
        35
    liuguangxuan  
    OP
       2023-12-26 13:26:32 +08:00
    @proxytoworld #18 老哥,我没有 pdb ,exe 是自动打包工具编译生成的。这种情况下如何定位问题呢?
    liuguangxuan
        36
    liuguangxuan  
    OP
       2023-12-26 13:27:18 +08:00
    @z4none #19 多谢老哥,我去了解一下。
    liuguangxuan
        37
    liuguangxuan  
    OP
       2023-12-26 13:28:11 +08:00
    @shuax #22 老哥牛。
    liuguangxuan
        38
    liuguangxuan  
    OP
       2023-12-26 13:28:53 +08:00
    @402124773 #25 老哥,我没有 pdb ,exe 是自动打包工具编译生成的。这种情况下如何定位问题呢?
    JerryV2
        39
    JerryV2  
       2023-12-26 14:37:09 +08:00
    两个比较靠谱的方式:

    1 、使用 winDbg

    2 、使用远程调试
    liuguangxuan
        40
    liuguangxuan  
    OP
       2023-12-26 15:29:01 +08:00
    @JerryV2 #39 老哥,”使用远程调试“指的是在开发机器上,使用附加进程的方式,附加到客户机器上的 exe 吗?
    proxytoworld
        41
    proxytoworld  
       2023-12-26 15:30:48 +08:00
    @liuguangxuan 你是什么语言打包的 exe ,python ?
    ashong
        42
    ashong  
       2023-12-26 15:47:45 +08:00 via iPhone   ❤️ 1
    @liuguangxuan 每次编译生成的 pdb 包含源码信息,如果源码修改后 kb 会找不到正确的对应代码行,保留好版本对应的 pdb 和 git commit 就没问题了
    sloknyyz
        43
    sloknyyz  
       2023-12-26 16:09:05 +08:00   ❤️ 1
    没 pdb 这个崩溃就算了,别看了。重新编译一次,把 pdb 保留好,把新程序给用户替换,让用户复现,等拿到新 dump 再分析。
    liuguangxuan
        44
    liuguangxuan  
    OP
       2023-12-26 16:09:36 +08:00
    @proxytoworld #41 开发语言 C++,打包的是 buildbot 。
    GreyWang
        45
    GreyWang  
       2023-12-26 16:30:45 +08:00
    @liuguangxuan 自动打包工具如 Jenkins 是可以指定将 pdb 、dll 文件保存的,找配置同事修改一下打包工具的配置就行了,打包结束后自动将 pdb 文件上传至 ftp 服务器,然后你再去下载下来应对后续的问题分析。
    liuguangxuan
        46
    liuguangxuan  
    OP
       2023-12-26 16:35:34 +08:00
    @GreyWang #45 棒,老哥!
    有没有 Windows 下 C++的其他调试技巧或者最佳实践,老哥传授一下呀😁
    daimiaopeng
        47
    daimiaopeng  
       2023-12-26 17:58:00 +08:00   ❤️ 1
    直接用 vs 打开 dump 文件,然后点本机调试,设置 pdb 和代码路径,可以看到奔溃的具体代码行(和平时调试一样)
    mmdsun
        48
    mmdsun  
       2023-12-26 19:38:06 +08:00 via iPhone   ❤️ 1
    什么框架开发的软件?一般都可以加一个全局的异常处理器,兜底没有处理的异常,在那里打印日志就行。
    JerryV2
        49
    JerryV2  
       2023-12-27 08:11:18 +08:00
    @liuguangxuan #40 是的,但是客户机上需要先启动 VS 的 Remote Debugger ,如果有防火墙需要开对应的端口,教程有很多,一看就会
    liuguangxuan
        50
    liuguangxuan  
    OP
       2023-12-27 08:19:55 +08:00
    @JerryV2 #49 这样是不是需要在客户机上运行 Debug 版本?但是 Debug 版本依赖太多以 d 结尾的 dll ,比如 msvcp100d.dll mfc100d.dll 等,估计要在客户机器上安装完整的开发环境了。
    JerryV2
        51
    JerryV2  
       2023-12-27 08:39:12 +08:00   ❤️ 1
    @liuguangxuan #50 release 版就可以,如果是带调试信息的就更好了
    jones2000
        52
    jones2000  
       2023-12-27 12:27:47 +08:00
    windbg
    GreyWang
        53
    GreyWang  
       2023-12-28 09:18:31 +08:00   ❤️ 1
    @liuguangxuan 如果你的程序集成了其他的子模块,通过头文件和动态库 dll 或者静态库 lib 的方式编译,可以要到子模块的源码,和子模块的头文件放到一起,如果崩溃发生在子模块里,通过调试 dump 可以直接定位到子模块的源码代码行,不需要再手动搜索一遍源文件来定位崩溃点。
    james19820515
        54
    james19820515  
       137 天前
    有结论了吗?
    liuguangxuan
        55
    liuguangxuan  
    OP
       137 天前
    @james19820515 你想知道什么?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1101 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 19:25 · PVG 03:25 · LAX 11:25 · JFK 14:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.