debugging 调试MFC头代码不适用于Visual Studio 2019

eh57zj3b  于 2023-03-23  发布在  其他
关注(0)|答案(3)|浏览(237)

TL;DR:调试 into MFC(CString)头代码在 * 两台 * 我的机器上都不起作用,据我所知,这是由于这些头代码的编译方式特殊。

当通过反汇编输入MFC头代码时,单步执行可以工作,但设置断点不起作用。
我正在寻找一个变通办法或至少承认我的分析。
系统:

  • Visual Studio 2019专业版16.9.6
  • Windows 10 / 1809企业版LTSC
    设置:(我很抱歉这是相当长的。)
  • 创建Visual Studio 2019示例MFC应用程序项目(SDI应用程序)
  • 确保Enable Just My Code在Options -〉Debugging -〉General下off
  • 将构建配置设置为Debug/x64(这没有什么区别,但让我们都保持在同一页上)
  • 导航到MFCApplication1.cpp-〉CMFCApplication1App::InitInstance()
  • 插入一个CString init,如下所示:
...
  InitCommonControlsEx(&InitCtrls);

  CWinAppEx::InitInstance(); // please put breakpoint 1 here

  // Add this line and set breakpoints
  CString this_is_text(L"Debugging into CString Header does not work!"); // breakpoint 2 here

现在,您可以在调试器下启动程序,并且应该在第一个断点处停止:

现在,确保所有符号都已加载,最简单的方法是通过调用堆栈:

只需选择调用堆栈窗口中的所有行,然后点击上下文菜单中的Load Symbols。之后,调用堆栈应该大致如下所示:

>  MFCApplication1.exe!CMFCApplication1App::InitInstance() Line 75 C++
        mfc140ud.dll!AfxWinMain(HINSTANCE__ * hInstance=0x00007ff7b5070000, ...) Line 37    C++
        MFCApplication1.exe!wWinMain(HINSTANCE__ * hInstance=0x00007ff7b5070000, ...) Line 26   C++
        MFCApplication1.exe!invoke_main() Line 123  C++
        MFCApplication1.exe!__scrt_common_main_seh() Line 288   C++
        MFCApplication1.exe!__scrt_common_main() Line 331   C++
        MFCApplication1.exe!wWinMainCRTStartup(void * __formal=0x000000c2b7084000) Line 17  C++
        kernel32.dll!BaseThreadInitThunk()  Unknown
        ntdll.dll!RtlUserThreadStart()  Unknown

现在,您可以尝试 * 逐步进入 *(可能是F11)CWinAppEx::InitInstance()函数,它应该可以毫无问题地 * 工作 *,使您进入mfc140ud.dll!CWinApp::InitInstance() Line 394-这是可以的。
再次退出,然后尝试单步执行CString ctor:

这在我的机器上不起作用!
然而,我能做的是(从上面的观点)切换到反汇编视图,进入call s,并以这种方式进入头代码:

然后我就可以成功地单步执行MFC头代码(但永远不会进入)。尝试设置断点将导致错误:
当前不会命中断点。没有调试器代码类型的可执行代码与此行关联。可能的原因包括...
C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.28.29910\atlmfc\include\cstringt.h

这就是我现在的处境。

分析

从MFC代码中我们可以看到,我们可以单步执行“常规”cpp代码,但是一旦我们尝试单步执行(或设置断点)CStringt.h内部的代码,它就会中断。
这里很特别:这是template header code,但执行的代码(如反汇编所示)并不在用户模块中,而是在mfc###.dll中!我认为他们对预处理器做了一些聪明的技巧(参见defined(_MFC_DLL_BLD)和一些类似的东西),这使得头文件可以多次使用,也许,这也是破坏调试器的原因。

问题

  • 这是一个已知的问题吗?所有VS 2019安装都会发生这种情况吗?我的设置是否有什么特殊之处?
  • 可能在更新的VS版本中修复?
  • 如果这实际上是坏的,什么将是一个可用的解决办法,而不是不断切换到反汇编视图时,进入MFC头。

这里最有趣的答案实际上是为什么会中断-调试器在哪里会感到困惑?这是调试库代码时重新执行代码的一般问题吗?

wwwo4jvm

wwwo4jvm1#

MSVC附带的源不匹配。
我认为这种情况会发生,因为DLL用Windows Update或新的vcredit更新了,但Visual Studio包含没有更新。如果使用/MT/MTd生成并静态链接MFC,则问题不会持续存在。
如果您关心的话,可能可以将此报告给http://developercommunity.visualstudio.com

解决方法1

执行@selbie描述的步骤:
1.在要单步执行的代码行上设置断点。
1.当到达断点时,在编辑器窗口中右键单击并选择“转到反汇编”。
1.在反汇编模式下,一步一步走到call语句。[...]您可以通过再次右键单击并选择“转到源代码”来退出反汇编模式。
(跳过与此问题无关的部分)
然后手动拾取头的位置,调试器将告诉它不匹配。尽管差异似乎微不足道,所以头是可用的。

解决方法2

静态链接MFC,使用/MT/MTd编译

解决方法3

ATL有一个类似的CString,它没有这个问题:

#include <atlbase.h>
#include <atlstr.h>

int main() {
    ATL::CString this_is_text("Debugging into CString header works");
}
pgx2nnw8

pgx2nnw82#

分析在某个时候出现了偏差,但我们最终发现了问题的一部分:
Require source files to exactly match the original version选项:

是个问题,但方式很特别
如果不需要源文件匹配(即禁用此默认选项),则OP会出现错误行为:调试器无法再将符号与cstringt.h文件匹配。
不幸的是,我在两台机器上都禁用了这个功能。拉入第三台机器表明我们可以设置断点(尽管F11仍然不起作用),通过比较VS设置的xml导出,我们发现这是不同的。
所以长话短说对于我们来说,为了能够在(未修改的!)MFC头中设置断点,需要我们 * 启用 * Require source files to exactly match ..选项。
如果禁用该选项(这意味着调试器的行为更为宽松),则该选项将不再工作。
而且,是的,我们反复检查了C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.28.29910\atlmfc\include\cstringt.h中的源文件始终相同
step-into/F11的神秘仍然存在,但我想这最好是一个单独的问题。

t3psigkw

t3psigkw3#

取消选中工具-〉选项-〉调试中的启用仅我的代码选项

我知道这适用于c++ std::库代码调试。当我忘记取消选中此选项时,我使用的另一种技术与您上面描述的类似。
1.在要单步执行的代码行上设置断点。
1.当到达断点时,在编辑器窗口中右键单击并选择“转到反汇编”。
1.在反汇编模式下,跳转到call语句。这通常是std库。最终,您将导航到汇编和系统代码源的混合。您可以通过再次右键单击并选择“转到源代码”来退出反汇编模式。

相关问题