最近单步调试MFC对话框程序时,发现了一个奇怪的现象,可能是我OUT了,请大家帮忙分析一下。
重现:用VS(2005或2008均可)创建一个MFC对话框程序,就用默认的代码即可。在CXXXDlg.cpp文件里,有如下代码:CdlgtestDlg dlg;
m_pMainWnd = &dlg;
nResponse = dlg.DoModal();这段代码实际就是创建并显示对话框的,运行没有问题。现在把上面的代码修改一下,加点东西:CdlgtestDlg dlg;
m_pMainWnd = &dlg;
nResponse = dlg.DoModal();CdlgtestDlg dlg2;
m_pMainWnd = &dl2g;
nResponse = dlg2.DoModal();
代码的实际意思就是在退出第一个对话框后,马上重新创建一个对话框并显示,奇怪的是,第二个对话框会自动退出,并且可能会给出如下信息:
“dlgtest.exe”: 已加载“C:\Windows\System32\cryptbase.dll”,未加载任何符号。
Error: CWinThread::PumpMessage called when not permitted.
Detected memory leaks!
Dumping objects ->
c:\users\chenlanbo\documents\visual studio 2005\projects\dlgtest\dlgtest\dlgtest.cpp(67) : {143} client block at 0x001EC670, subtype c0, 120 bytes long.
a CDialog object at $001EC670, 120 bytes long
Object dump complete.
程序“[1036] dlgtest.exe: 本机”已退出,返回值为 3 (0x3)。各位大虾,谁能告诉我这是为什么啊?我需要重新创建对话框。以上是测试代码,在我的程序里,是会抛出一个CResourceException异常,然后MFC在处理这个异常的时候挂掉。。
挂掉的原因是在IsDerivedFrom()函数中,一层一层往上寻找baseclass时某次得到一个空指针,它直接拿来用了,如下(我写的是一个DLL,里面使用的对话框):
BOOL CRuntimeClass::IsDerivedFrom(const CRuntimeClass* pBaseClass) const
{
ENSURE(this != NULL);
ASSERT(AfxIsValidAddress(this, sizeof(CRuntimeClass), FALSE));
ENSURE(pBaseClass != NULL);
ASSERT(AfxIsValidAddress(pBaseClass, sizeof(CRuntimeClass), FALSE)); // simple SI case
const CRuntimeClass* pClassThis = this;
#ifdef _AFXDLL
for (;;)
#else
while (pClassThis != NULL)
#endif
{
if (pClassThis == pBaseClass)
return TRUE;
#ifdef _AFXDLL
if (pClassThis->m_pfnGetBaseClass == NULL) // 这里挂了,while没有对pClassThis作NULL判断
break;
pClassThis = (*pClassThis->m_pfnGetBaseClass)(); //这里,某次取出来了一个NULL值,赋给了pClassThis
#else
pClassThis = pClassThis->m_pBaseClass;
#endif
}
return FALSE;       // walked to the top, no match
}

解决方案 »

  1.   

    把 CdlgtestDlg dlg;
    m_pMainWnd = &dlg;
    nResponse = dlg.DoModal();CdlgtestDlg dlg2;
    m_pMainWnd = &dl2g;
    nResponse = dlg2.DoModal();改成
    CdlgtestDlg dlg;
    nResponse = dlg.DoModal();CdlgtestDlg dlg2;
    m_pMainWnd = &dl2g;
    nResponse = dlg2.DoModal();
    试试...
      

  2.   

    你自己的代码里有错误. Dlg1 或 Dlg2里。const CRuntimeClass* pClassThis = this;pClassThis 成 NULL 了,也就是 this 是 NULL
    说明你有
    等效于
    NULL->Function()
    的语句。
      

  3.   


    this是没有问题的, 在while里会有以下操作:
    pClassThis = (*pClassThis->m_pfnGetBaseClass)(); //这里,某次取出来了一个NULL值,赋给了pClassThis是这里把pClassThis赋成空的了, 不是一上来就是空的。
      

  4.   

    this是没有问题的, 在for(;;)里会有以下操作(DLL程序,所以不是while):
    pClassThis = (*pClassThis->m_pfnGetBaseClass)(); //这里,某次取出来了一个NULL值,赋给了pClassThis是这里把pClassThis赋成空的了, 不是一上来就是空的。
      

  5.   


    高手果然是高手!!!! 
    我试了一下,果然是可以弹出来了,但是是为什么呢?
    在我自己的代码里,是这样的:我写了一个对话框的类,CDlg,DLL里会创建一个线程,线程里的处理主要就是创建对话框:
    int ThreadProc(…)
    {
    ……
    CdlgtestDlg dlg1;
    nResponse = dlg1.DoModal();
    CdlgtestDlg dlg2;
    nResponse = dlg2.DoModal();
    ……
    }
    第一个对话框很正常,第二个对话框Domodal时会抛出CResourceException, 这个可能是什么原因呢?
    代码在公司,不好帖代码,大家见谅