无法调试 C++ 可执行文件(“断点当前不会被命中”)

Posted

技术标签:

【中文标题】无法调试 C++ 可执行文件(“断点当前不会被命中”)【英文标题】:Unable to debug C++ executable ("The breakpoint will not currently be hit") 【发布时间】:2020-06-26 20:33:19 【问题描述】:

我在 Windows 10 上的 Visual Studio 2019 (16.4.2) 中有一个链接 C++ 静态库的测试可执行文件。当我启动调试器时,测试 cilent 和库代码中的所有断点都显示为空心,并带有 PDB 的工具提示找不到:

“当前不会命中断点。没有为此文档加载任何符号。”

启动调试器后,从“未加载符号”屏幕上的链接手动浏览可执行 PDB 也会失败并显示以下消息:

“在此文件夹中找不到匹配的符号文件”

这个奇怪的文件在那里,它是最新的,而且 PDB 浏览器让我选择它。它是正确的 PDB(在链接器 > 调试设置中指定),而不是更小的中间文件夹。

我正在构建 Debug|x86 并在 Debug|x64 中遇到相同的问题。我的测试可执行文件使用的是 Google 测试版本 1.8.1.2。

我已尝试删除所有中间文件和输出,关闭/重新打开 IDE 并重建解决方案,但这没有帮助。 PDB 没有被其他项目中的同名数据库覆盖。

我的项目设置如下:

测试可执行和静态库:

C/C++ > 常规:调试信息格式 = 程序数据库 (/Zi)。

测试可执行文件:

链接器 > 调试:生成调试信息 = 生成调试信息 (/DEBUG)

链接器 > 调试:生成程序数据库文件 = $(OutDir)$(TargetName).pdb

第 3 方 Google 测试 PDB 存在于输出文件夹中,由我正在使用的 NuGet 包中的构建复制。我已经检查了这些是正确的 PDB。我不认为我需要这些,因为我没有尝试调试任何 Google 测试代码。

我已尝试创建一个新的“Hello world”测试可执行文件,并且可以毫无问题地对其进行调试。

【问题讨论】:

我认为,如果您查看调试器输出窗格,您可以看到更多关于为什么没有加载 PDB 的信息。有时它认为 PDB 已过时(陈旧);有一个选项可以让调试器加载并使用这些陈旧的 PDB。 由于名称冲突,它似乎在中间符号和输出符号之间混淆了(见下面的答案) - 最后只是报告它找不到它们。 【参考方案1】:

经过反复试验,我找到了答案。

具有可执行目标(EXE 或 DLL)的项目会生成 两个 PDB:

    Intermediate PDB:仅用于项目代码,写入中间文件夹

配置属性> C/C++:程序数据库文件名中指定

    输出 PDB:针对包括静态链接库在内的整个可执行文件,写入输出文件夹

配置属性>链接器>调试:生成程序数据库文件中指定

问题是由覆盖可执行文件的 intermediate PDB 的名称引起的,将其从默认值更改为项目(又名目标)名称。输出 PDB(大得多并写入输出文件夹)共享相同的文件名。

中间 PDB 名称覆盖继承自与静态库项目共享的公共属性页。后者需要此覆盖,因为它随其 PDB 一起分发。保留默认名称 (vc142.pdb) 可能会与其他默认名称 PDB 冲突。

修复是在可执行项目中恢复中间 PDB 的默认名称:

    打开项目属性。 扩展配置属性 > C/C++ 恢复程序数据库文件名的值:从值下拉列表中选择 。点击应用。

这会将值重新设置为 $(IntDir)vc$(PlatformToolsetVersion).pdb

悬崖:任何 DLL/EXE 项目都应避免为其中间和最终(输出)PDB 指定相同的 PDB 文件名。

链接器在这方面可能会更有帮助,也许是在发生此类用户生成的冲突时发出链接时警告。

【讨论】:

以上是关于无法调试 C++ 可执行文件(“断点当前不会被命中”)的主要内容,如果未能解决你的问题,请参考以下文章

无法调试 - “断点当前不会被命中。没有为此文档加载任何符号”

VS 2010 远程调试器断点当前不会被命中。没有为此文档加载任何符号

断点当前不会被命中。没有为此文档加载任何符号

调试由 .NET 应用程序创建的 COM 对象

“断点目前不会被击中。没有为此文档加载任何符号。” - .pdb 从错误的地方加载?

使用 devenv 在 C++ 可执行文件中调试回调