我有一个用 c++98 编写的应用程序,它在 32 位中运行良好。但在 64 位中它随机开始崩溃。也许在 10 次它不会突然崩溃它连续崩溃 3 次。
此崩溃发生在菜单栏的创建过程中。这个菜单栏是一个继承自CToolBar
的类。
const DWORD dwStyle = WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_TOOLTIPS | CBRS_FLYBY;
m_menuBar.SetSizes( CSize( 16,15 ), CSize( 1,1 ) );
const BOOL bCreated = m_menuBar.CreateEx( this, TBSTYLE_FLAT | TBSTYLE_LIST, dwStyle, CRect(0,0,0,0), AFX_IDW_TOOLBAR );
最近根据我们经理的决定,我们从 Visual Studio 2010 更新到 Visual Studio 2019,现在系统性地在 64 位系统中发生崩溃,而在 32 位系统中仍然不会发生。
可能是什么问题?
编辑添加我的堆栈:
Kernel.dll!000000001f009540()
user32.dll!00007fff7c7c63ed()
user32.dll!00007fff7c7c5fbc()
user32.dll!00007fff7c7d28d3()
ntdll.dll!00007fff7e4dfe14()
win32u.dll!00007fff7c4c1f24()
user32.dll!00007fff7c7b8011()
user32.dll!00007fff7c7b7c04()
user32.dll!00007fff7c7db122()
mfc140d.dll!00007fff3ba05208()
mfc140d.dll!00007fff3b9f4e56()
mfc140d.dll!00007fff3b9f4715()
mfc140d.dll!00007fff3b84a4c3()
d.exe!CDcmMainFrame::CreateMenuBar() Line 1001
d_d.exe!CDcmMainFrame::OnCreate(tagCREATESTRUCTA * lpCreateStruct) Line 925
[External Code]
d_d.exe!CVSDicomApp::InitInstance() Line 3074
[External Code]
d.exe!WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int nCmdShow) Line 26
d_d.exe!main(int ac, char * * av) Line 24
[External Code]
最佳答案
根本原因很可能位于您发布的代码之外,并且与无效的指针转换有关。了解更多关于代码上下文的信息会很有帮助。 我能想到的:
- 您发布的代码位于 CWnd 派生类的方法内。
- 指向该类的指针被转换并存储在一个 32 位整数中。
- 该方法是通过指向该类的指针调用的,该指针是通过将 32 位整数转换回您的类的指针而生成的。
- 在 64 位系统上,这会导致清除指针的高 32 位。
- 如果这些位为零,则不会发生任何事情,因为指针没有改变。
- 如果这些位不为零,则指针会损坏并指向无效的内存区域。最后,这个损坏的指针在调用 CreateEx 时用“this”表示,最终访问了错误的内存位置。
- 在 32 位系统上,代码可以工作,因为指针只有 32 位,并且在转换为 32 位整数时不会被截断。
您可以尝试以下方法:
插入一个
Trace("*** MyClass = %p ***\n", this);
在 CreateEx 调用之前直接调用您的类的构造函数。如果发生崩溃,两个调试输出是否匹配?
您可以尝试的另一件事是为 CreateEx 调用设置一个断点,以便在调用 CreateEx 之前停止执行。然后检查“this”指针。类(class)的所有成员看起来都有效吗?特别是 m_hWnd 应该是 != NULL。 (当然,这必须针对发生崩溃的情况进行评估,因此您可能需要尝试多次,因为您事先不知道。)另外,您可能会在创建“this”后直接输出一次m_hWnd "窗口并直接在 CreateEx 调用之前。它们相等吗?
如果我没看错,代码位于您的主应用程序中 - 而不是在 dll 中,对吗? (过去在 dll 中创建 MFC 对象时以及忘记 AFX_MANAGE_STATE 宏时我有一些奇怪的行为。)
您是否在您的应用程序中使用多线程?可能是 CreateEx 调用有时是由不同的线程完成的?当在一个类中混合来自不同线程的 MFC 调用时,MFC 会遇到麻烦。您可以将上面的调试输出扩展到
Trace("*** MyClass = %p, ThreadId = %u ***\n", this, GetCurrentThreadId());
(线程 ID 应始终与“this”指针相等。)
关于c++ - CToolBar MFC 64 位在 32 位上运行时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58972404/