c++ - CToolBar MFC 64 位在 32 位上运行时崩溃

标签 c++ .net mfc

我有一个用 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/

相关文章:

c# - 如何使用 Azure AD 生成具有角色定义的 token

c# - 为 Access mdb 文件创建 OdbcConnection 的 ConnectionString 是什么

C++如何触发PostMessage在另一个线程中进行

c++ - 如何在 MFC 应用程序首次启动时禁用自动文档/ View 创建

c++ - 无法将参数 1 从 'ATL::CStringT<wchar_t,ATL::StrTraitATL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>' 转换为 'const char *'

c++ - ungetc 有 C++ 版本吗?

c++ - 动态转换抛出指针不是 std::__non_rtti_object

.net - 使用不返回 Json(而是另一个 View )的 JQuery AJAX 调用 MVC 操作

c++ - 如何在不将它们作为参数传递的情况下访问线程中的类数据成员?

c++ - 在 jemalloc 中获取每个内存分配的 bin 大小