[英]How does the MFC PropertyGrid control work in the dialog editor in visual studio?
[英]Debugging into MFC header code does not work with Visual Studio 2019
TL;DR :调试到MFC ( CString
) header 代码在我的两台机器上都不起作用,据我所知,这是由于这些头文件的特殊编译方式。
通过反汇编输入时,逐步通过 MFC header 代码有效,但设置 brealpoints 不起作用。
我正在寻找解决方法或至少确认我的分析。
系统:
设置:(我很抱歉这很长。)
创建 Visual Studio 2019 示例 MFC 应用程序项目(SDI 应用程序)
确保在 Options -> Debugging -> General 下关闭Enable Just My Code
。
将构建配置设置为 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
现在,您可以在调试器下启动程序,并且应该在第一个断点处停止:
现在,确保所有符号都已加载,最简单的方法是通过调用堆栈完成:
只需 select 调用堆栈 window 中的所有行,然后在上下文菜单中点击加载符号。 之后调用堆栈应大致如下所示:
> 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()
function,它应该可以正常工作,让您进入mfc140ud.dll:CWinApp::InitInstance() Line 394
行。
再次退出,然后尝试进入CString
ctor:
这在我的机器上不起作用!
然而,我能做的是(从上面的观点)切换到反汇编视图,进入那里的call
并以这种方式进入 header 代码:
然后我可以成功地通过(但永远不会进入)MFC header 代码。 尝试设置断点会导致错误:
当前不会命中断点。 没有调试器代码类型的可执行代码与此行相关联。 可能的原因包括...
C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.28.29910\atlmfc\include\cstringt.h
这就是我所在的位置。
分析:
从 MFC 代码中我们可以看到,我们可以进入“常规”cpp 代码,但是一旦我们尝试进入(或设置断点)这个CStringt.h
中的代码,它就会中断。
特殊之处:这是模板header代码,但执行的代码(如反汇编所示)仍然不在用户模块中,而是在mfc###.dll
! 我认为他们使用预处理器做了一些聪明的技巧(参见defined(_MFC_DLL_BLD)
和一些类似的),这使得 header 文件的这种多重使用成为可能,也许这也是破坏调试器的原因。
问题:
这里最有趣的答案实际上是关于为什么会中断 - 调试器在哪里感到困惑? 这是调试库代码时重新define
代码的普遍问题吗?
MSVC 附带的源不匹配。
我认为会发生这种情况,因为 DLL 使用 Windows 更新或新的 vcredist 进行了更新,但 Visual Studio 包含的内容未更新。 如果您使用/MT
或/MTd
并静态链接 MFC,则问题不会持续存在。
如果您愿意,可能可以将此报告给http://developercommunity.visualstudio.com 。
解决方法 1
执行@selbie 描述的步骤:
- 在我要进入的代码行上设置断点。
- 到达断点后,在编辑器 window 和 select 中右键单击“Go To Disassemly”。
- 在反汇编模式下,单步执行直到到达
call
语句。 [...]您可以通过再次右键单击并选择“转到源代码”来退出反汇编模式。
(跳过与此问题无关的部分)
然后手动拿起 header 的位置,调试器会告诉它不匹配。 虽然差异似乎微不足道,因此 header 是可用的。
解决方法 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");
}
分析在某个时候出现了偏差,但我们最终在这里发现了问题的一部分:
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 的谜团仍然存在,但我想这最好被带到一个单独的问题上。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.