为啥从属性页调用afxmessagebox到扩展dll时mfc死锁

Posted

技术标签:

【中文标题】为啥从属性页调用afxmessagebox到扩展dll时mfc死锁【英文标题】:Why mfc deadlock when calling a afxmessagebox from propertypage into a extension dll为什么从属性页调用afxmessagebox到扩展dll时mfc死锁 【发布时间】:2016-09-27 07:25:52 【问题描述】:

我有一个 mfc 应用程序和一个带有模态对话框的扩展 dll。在此对话框中是一个 PropertySheet。属性页之一是从 extnsion dll 加载的。进入扩展 DLL 的是另一个属性表。如果我想在 dll 的 poperty 表中打开一个 AfxMessageBox,则应用程序会挂起。 我认为有一个僵局。 操作系统是 Windows 7。 IDE Visual-Studio 2012

这是 CallStack 的一些行。

>   mfc110d.dll!_AfxTraceMsg(const char * lpszPrefix, const tagMSG * pMsg) Zeile 302    C++
mfc110d.dll!AfxCallWndProc(CWnd * pWnd, HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Zeile 275   C++
mfc110d.dll!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Zeile 453    C++
mfc110d.dll!AfxWndProcBase(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Zeile 304    C++
user32.dll!76a362fa()   Unnamed
[The frames below are possible corrupted or not here. No symbols loaded foruser32.dll]  
user32.dll!76a36d3a()   Unknown
user32.dll!76a36ce9()   Unknown
user32.dll!76a3966e()   Unknown
user32.dll!76a396d5()   Unknown
user32.dll!76a6104b()   Unknown
user32.dll!76a60d62()   Unknown
user32.dll!76a61089()   Unknown
ntdll.dll!76f91171()    Unknown
user32.dll!76a362fa()   Unknown
ntdll.dll!76f91171()    Unknown
ntdll.dll!76f91171()    Unknown
ntdll.dll!76f91171()    Unknown
ntdll.dll!76f91171()    Unknown
user32.dll!76a36ce9()   Unknown
user32.dll!76a40d37()   Unknown
ntdll.dll!76f91171()    Unknown
ntdll.dll!76f91171()    Unknown
ntdll.dll!76f91171()    Unknown
mfc110d.dll!CWnd::DefWindowProcA(unsigned int nMsg, unsigned int wParam, long lParam) Line 1141 C++
mfc110d.dll!CWnd::Default() Line 323    C++
mfc110d.dll!CWnd::OnActivate(unsigned int __formal, CWnd * __formal, int __formal) Line 368 C++
mfc110d.dll!CMFCPropertyPage::OnActivate(unsigned int nState, CWnd * pWndOther, int bMinimized) Line 73 C++
mfc110d.dll!CWnd::OnWndMsg(unsigned int message, unsigned int wParam, long lParam, long * pResult) Line 2540    C++
mfc110d.dll!CWnd::WindowProc(unsigned int message, unsigned int wParam, long lParam) Line 2137  C++
mfc110d.dll!AfxCallWndProc(CWnd * pWnd, HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 290    C++
mfc110d.dll!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 453 C++
mfc110d.dll!AfxWndProcBase(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 304 C++
user32.dll!76a362fa()   Unknown
user32.dll!76a36d3a()   Unknown
user32.dll!76a36ce9()   Unknown
comctl32.dll!71f771cb() Unknown
comctl32.dll!71f33770() Unknown
mfc110d.dll!CMapPtrToPtr::HashKey(void * key) Zeile 42  C++
mfc110d.dll!CMapPtrToPtr::GetValueAt(void * key) Zeile 180  C++
0058ca3c()  Unbekannt
user32.dll!76a362fa()   Unknown
user32.dll!76a5f963()   Unknown
user32.dll!76a5f91b()   Unknown
user32.dll!76a5f7a4()   Unknown
ntdll.dll!76f91171()    Unknown
user32.dll!76a362fa()   Unknown
ntdll.dll!76f91171()    Unknown
ntdll.dll!76f91171()    Unknown
ntdll.dll!76f91171()    Unknown
ntdll.dll!76f91171()    Unknown
user32.dll!76a36ce9()   Unknown
user32.dll!76a40d37()   Unknown
ntdll.dll!76f91171()    Unknown
ntdll.dll!76f91171()    Unknown
ntdll.dll!76f91171()    Unknown
mfc110d.dll!CWnd::DefWindowProcA(unsigned int nMsg, unsigned int wParam, long lParam) Zeile 1141    C++
mfc110d.dll!CWnd::WindowProc(unsigned int message, unsigned int wParam, long lParam) Zeile 2138 C++
mfc110d.dll!AfxCallWndProc(CWnd * pWnd, HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Zeile 290   C++
mfc110d.dll!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Zeile 453    C++
mfc110d.dll!AfxWndProcBase(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Zeile 304    C++
user32.dll!76a362fa()   Unknown
user32.dll!76a36d3a()   Unknown
user32.dll!76a36ce9()   Unknown
user32.dll!76a36ded()   Unknown
user32.dll!76a36e4c()   Unknown
ntdll.dll!76f3011a()    Unknown
user32.dll!76a4219a()   Unknown
user32.dll!76a8ef0a()   Unknown
user32.dll!76a362fa()   Unknown
user32.dll!76a5f9ff()   Unknown
user32.dll!76a5f91b()   Unknown
user32.dll!76a5f7a4()   Unknown
user32.dll!76a4afbc()   Unknown
user32.dll!76a362fa()   Unknown
user32.dll!76a36d3a()   Unknown
user32.dll!76a36ce9()   Unknown
user32.dll!76a40d37()   Unknown
user32.dll!76a4795a()   Unknown
mfc110d.dll!_AfxActivationWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Zeile 489 C++
user32.dll!76a362fa()   Unknown
user32.dll!76a36d3a()   Unknown
user32.dll!76a36ce9()   Unknown
user32.dll!76a3966e()   Unknown
user32.dll!76a6208f()   Unknown
user32.dll!76a5cf5b()   Unknown
user32.dll!76a8f808()   Unknown
user32.dll!76a8fae4()   Unknown
user32.dll!76a8fbe7()   Unknown
user32.dll!76a8fc66()   Unknown
user32.dll!76a8fdb9()   Unknown
user32.dll!76a8fdfe()   Unknown
mfc110d.dll!CWinApp::ShowAppMessageBox(CWinApp * pApp, const char * lpszPrompt, unsigned int nType, unsigned int nIDPrompt) Zeile 128   C++
mfc110d.dll!CWinApp::DoMessageBox(const char * lpszPrompt, unsigned int nType, unsigned int nIDPrompt) Zeile 45 C++
mfc110d.dll!AfxMessageBox(const char * lpszText, unsigned int nType, unsigned int nIDHelp) Zeile 147    C++

这是 DLL 中的一些代码。 CPropStkList 派生自 CPropertyPage。

    void CPropStkList::OnBnClicked()

    //BOOL test = TryEnterCriticalSection(AfxGetThread());
    AfxMessageBox(_T("Hallo Test!!"));

    //CDialog dlg(IDD_DIALOG2);
    //dlg.DoModal();

这是调用 DLL-Dialog 的父应用程序的代码。

typedef UINT ( * LPDLLFUNC)(CGlobal *, CMsgSocket *); //Initialize DLL
    typedef CProSeSDialog * ( * GETDLG)(CWnd*, UINT, CString);   //Open Dialog from DLL
    LPDLLFUNC       lpfnDllFunc = NULL;
    GETDLG          getDlg  = NULL;
    HINSTANCE hDLL        = NULL;         
    hDLL = AfxLoadLibrary("Stammdaten_DLL.dll");
if(hDLL)
        
            lpfnDllFunc = (LPDLLFUNC)::GetProcAddress(hDLL,"Init");
            getDlg      = (GETDLG)::GetProcAddress(hDLL, "ShowDlg");
            if (!lpfnDllFunc)
            
                AfxMessageBox("Function not found in DLL");
                FreeLibrary(hDLL);
                //return;
            
            if(!getDlg)
            
                AfxMessageBox("Function getDlg not found in DLL");
                FreeLibrary(hDLL);
            
            lpfnDllFunc(AfxGetGlobal(), AfxGetGlobalSocket()); //Initialize DLL
            dlg[i=GetNewDlgNr()] = getDlg(this, 1, _T(""));

            m_strText[i] = INTLTXT ("Werkzeugstammdaten") + " DLL";



        
        else
        
            AfxMessageBox("Dll not found!");
        

在 DLL 中创建对话框

extern "C" AFX_EXT_API CProSeSDialog* ShowDlg(CWnd *parent, UINT dlgType = 0, CString strKey = _T(""))


    new CDynLinkLibrary(Stammdaten_DLLDLL);


    //Lege Einstiegsdaten fest
    CGlobalKeyBuffer &buffer =  CGlobalKeyBuffer::Instance();
    buffer.m_strKey = strKey;

    CViewDlg *test = new CViewDlg(WKZSTAMM);
    test->Create(IDD_DIALOG1, parent);


    return test;


更新 经过数小时调试应用程序后,我发现应用程序发送了一些消息。它永远不会以发送消息而结束。 这是发送的消息。

    <025111> 001F1316 S WM_GETDLGCODE
<025112> 001F1316 R WM_GETDLGCODE fuDlgCode:DLGC_WANTARROWS | DLGC_HASSETSEL | DLGC_WANTCHARS
<025113> 001F1314 S WM_GETDLGCODE
<025114> 001F1314 R WM_GETDLGCODE fuDlgCode:DLGC_WANTARROWS | DLGC_HASSETSEL | DLGC_WANTCHARS
<025115> 00201312 S WM_GETDLGCODE
<025116> 00201312 R WM_GETDLGCODE fuDlgCode:DLGC_WANTARROWS | DLGC_WANTCHARS
<025117> 001E130C S WM_GETDLGCODE
<025118> 001E130C R WM_GETDLGCODE fuDlgCode:DLGC_WANTARROWS | DLGC_WANTCHARS
<025119> 001F1308 S WM_GETDLGCODE
<025120> 001F1308 R WM_GETDLGCODE fuDlgCode:DLGC_STATIC
<025121> 001F1306 S WM_GETDLGCODE
<025122> 001F1306 R WM_GETDLGCODE fuDlgCode:DLGC_STATIC
<025123> 001E1304 S WM_GETDLGCODE
<025124> 001E1304 R WM_GETDLGCODE fuDlgCode:DLGC_STATIC
<025125> 001F1302 S WM_GETDLGCODE
<025126> 001F1302 R WM_GETDLGCODE fuDlgCode:DLGC_STATIC
<025127> 00211300 S WM_GETDLGCODE
<025128> 00211300 R WM_GETDLGCODE fuDlgCode:DLGC_STATIC
<025129> 001E12FE S WM_GETDLGCODE
<025130> 001E12FE R WM_GETDLGCODE fuDlgCode:DLGC_STATIC
<025131> 001E12FC S WM_GETDLGCODE

【问题讨论】:

你能把这些调用栈转换成英文吗? 请添加一些代码! 很难猜到跟踪是如何导致死锁的。启用 Microsoft 符号服务器以获得更好的堆栈跟踪。并考虑它可能根本不是死锁,因为它看起来不像,但消息框的所有者错误并显示在主窗口下方。看起来也像挂起一样,因为你不能再做任何事情了。使用调试器而不是消息框来验证代码是否运行,设置断点。 【参考方案1】:

我找到了解决问题的方法。 您必须将外部样式添加到具有任何子元素的每个元素(控件) WS_EX_CONTROLPARENT。

ModifyStyleEx(0, WS_EX_CONTROLPARENT);

如果这不起作用,您必须有很多子孩子。在 MFC 中超过三个是非常困难的。

【讨论】:

你拯救了我的一天

以上是关于为啥从属性页调用afxmessagebox到扩展dll时mfc死锁的主要内容,如果未能解决你的问题,请参考以下文章

打开 afxMessageBox 时未调用 mfc 事件

如何前端显示AfxMessageBox?

利用定时器模拟回车命令关闭AfxMessageBox窗口

JAVA中,子类将继承父类的所有属性和方法么~?为啥?

java中,子类的构造器为啥要调用父类构造器?

WPS在输入文字为啥会自动跳转到最后一页?