我在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”指针。类所有成员看起来都有效吗?特别是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在32位上运行时64位崩溃,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58972404/

    10-13 06:22