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头。
这里最有趣的答案实际上是为什么会中断-调试器在哪里会感到困惑?这是调试库代码时重新执行代码的一般问题吗?
3条答案
按热度按时间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
,它没有这个问题: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的神秘仍然存在,但我想这最好是一个单独的问题。
t3psigkw3#
取消选中工具-〉选项-〉调试中的启用仅我的代码选项
我知道这适用于c++ std::库代码调试。当我忘记取消选中此选项时,我使用的另一种技术与您上面描述的类似。
1.在要单步执行的代码行上设置断点。
1.当到达断点时,在编辑器窗口中右键单击并选择“转到反汇编”。
1.在反汇编模式下,跳转到
call
语句。这通常是std库。最终,您将导航到汇编和系统代码源的混合。您可以通过再次右键单击并选择“转到源代码”来退出反汇编模式。