一个使用动态链接库资源出错的难题

clever101
领域专家: C/C++技术领域
2008-03-07 10:49:16
在DLL弹出一个对话框,开始弹出对话框时出现“Debug Assertion Failed”,
上网搜了下,发现模块句柄的设置问题。然后作出如下解决:
1. 定义两个全局变量:

HINSTANCE g_hModuleInstance = NULL;
HINSTANCE g_hOldModuleInstance = NULL;

2.在DllMain函数中对g_hModuleInstance进行赋值:

g_hModuleInstance = hInstance;

3.在要使用对话框资源的类新建两个函数设置模块句柄。

void CAlternatExtractFun::SetResourceHandle()
{
g_hOldModuleInstance = AfxGetModuleState()-

>m_hCurrentResourceHandle;
AfxGetModuleState()->m_hCurrentResourceHandle = g_hModuleInstance;
}

void CAlternatExtractFun::RestoreResourceHandle()
{
AfxGetModuleState()->m_hCurrentResourceHandle

=g_hOldModuleInstance;
}

4.在使用对话框资源的函数里调用这两个函数:
void CAlternatExtractFun::Execute()
{

SetResourceHandle();

CAlterExtractDlg dlg;
dlg.DoModal();

RestoreResourceHandle();
}


但是运行时dlg.DoModal();这一行出错:Debug Assertion Failed!
然后调试进行:

在 CDialog::DoModal()函数中的
TRY
{
// create modeless dialog
AfxHookWindowCreate(this);
if (CreateDlgIndirect(lpDialogTemplate,
CWnd::FromHandle

(hWndParent), hInst))

在运行CreateDlgIndirect(lpDialogTemplate,
CWnd::FromHandle

(hWndParent), hInst)这一句出现Debug Assertion Failed!

再进入CreateDlgIndirect函数:
BOOL CWnd::CreateDlgIndirect(LPCDLGTEMPLATE lpDialogTemplate,
CWnd* pParentWnd, HINSTANCE hInst)
{

#ifdef _DEBUG
if ( AfxGetApp()->IsKindOf( RUNTIME_CLASS( COleControlModule ) ) )
{
TRACE(traceAppMsg, 0, "Warning: Creating dialog from

within a COleControlModule application is not a supported scenario.\n");
}
#endif

在AfxGetApp()->IsKindOf( RUNTIME_CLASS( COleControlModule ) 出错。

然后上网搜索CreateDlgIndirect函数。网上有个说法说是
#ifdef _DEBUG
if ( AfxGetApp()->IsKindOf( RUNTIME_CLASS( COleControlModule ) ) )
{
TRACE(traceAppMsg, 0, "Warning: Creating dialog from

within a COleControlModule application is not a supported scenario.\n");
}
#endif

是VS C++ 2005+sp1的一个bug.下面是网友的一个算法:

楼主wangjia184(我就是传说中的。。。。。。SB)2006-10-24 14:36:40 在

VC/MFC / 基础类 提问
先说说程序的结构


这是一个VS2005的插件,属ATL
ATL中隐式链接到一个MFC DLL,MFC DLL中是有Dialog
以前使用 盗版的VS2005 中文版, 没打补丁。一切正常


这2天把系统重装了,换成了正版的VS2005英文版,还打了SP1(Beta)补丁
问题就出现了!

当Dialog DoModal()的时候,报错。

错误堆栈如下:
DoModal() 调用了 CreateDlgIndirect()



CreateDlgIndirect 中最开始有一段:
#ifdef _DEBUG
if ( AfxGetApp()->IsKindOf( RUNddTIME_CLASS( COleControlModule

) ) )
{
TRACE(traceAppMsg, 0, "Warning: Creating dialog from within

a COleControlModule application is not a supported

scenario.\n");
}
#endif

其中的AfxGetApp返回NULL, 我的DLL入口是DllMain,这个AfxGetApp肯定会返回

NULL
所以在这里报错了


使用Release 版本运行,一切正常, 好像这段是打了SP1加上去的。

我晕死了 难道以后都要在Release版本下调试?
问题点数:50、回复次数:5



不知大家怎么认为,还有我的问题怎么解决呢?

我的编译环境:
win xp sp2
VS C++ 2005+ sp1
intel 双核处理器
...全文
1492 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
yanweiqi 2010-07-20
  • 打赏
  • 举报
回复
我遇到的情况和楼主一样,在同样的地方出现的异常。
我的是在ATL的插件中有对话框资源及类,将对话框ID和类的CRuntimeClass传递给EXE,EXE将对话框类(继承的是FormView)添加到EXE的Pane中。

也是Release版运行正常,由于CreateDlgIndirect函数中的
#ifdef _DEBUG
if ( AfxGetApp()->IsKindOf( RUNTIME_CLASS( COleControlModule ) ) )
{
TRACE(traceAppMsg, 0, "Warning: Creating dialog from within a COleControlModule application is not a supported scenario.\n");
}
#endif
据说原因是在ATL中AfxGetApp()返回总是空所致,不知道该怎么办了,有没有高手知道原因,楼主后来是怎么解决的???
red-fly 2008-11-24
  • 打赏
  • 举报
回复
我的程序调试时也发现总是打印IsKindOf下面的那一句:
Warning: Creating dialog from within a COleControlModule application is not a supported scenario.
但我好像也没有看到其它有什么异常,所以现在也不管它了

我看楼主的问题是资源的问题,在对话框的属性中修改它的ID,比如把IDD_ALTEREXT改为 IDD_DLG_MYDLG等等,然后全部重新编译,或者是关掉VC再重新打开工程全部重新编译也许会解决问题
cnzdgs 2008-03-09
  • 打赏
  • 举报
回复
问一下,你的EXE程序是那种项目模板,在什么时候调DLL中的对话框?
clever101 2008-03-09
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 cnzdgs 的回复:]
是SetResourceHandle,Copy错了。
这样改过之后紧接着执行AfxGetApp看看返回的是NULL吗?因为你13楼说调试的时候CObject::IsKindOf中的ENSURE(this != NULL)出错。
[/Quote]

这样改过之后紧接着执行AfxGetApp返回的还是NULL。
cnzdgs 2008-03-09
  • 打赏
  • 举报
回复
是SetResourceHandle,Copy错了。
这样改过之后紧接着执行AfxGetApp看看返回的是NULL吗?因为你13楼说调试的时候CObject::IsKindOf中的ENSURE(this != NULL)出错。
clever101 2008-03-09
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 cnzdgs 的回复:]
你把RestoreResourceHandle函数改一下:
AfxGetModuleState()-> m_hCurrentResourceHandle = LoadLibrary();
这样试试。
[/Quote]

这样做还是出现“Debug Assertion Failed”的错误。
clever101 2008-03-09
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 cnzdgs 的回复:]
你把RestoreResourceHandle函数改一下:
AfxGetModuleState()-> m_hCurrentResourceHandle = LoadLibrary();
这样试试。
[/Quote]

大侠,你说把RestoreResourceHandle函数改一下,应该是把SetResourceHandle()函数改一下吧。
cnzdgs 2008-03-09
  • 打赏
  • 举报
回复
看来是遇到bug了。你再把SetResourceHandle和RestoreResourceHandle改成用AfxSetResourceHandle试试,不过感觉可能没什么作用。
clever101 2008-03-09
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 cnzdgs 的回复:]
问一下,你的EXE程序是那种项目模板,在什么时候调DLL中的对话框?
[/Quote]


这个系统是采用插件式进行开发的,主体EXE程序是一个多文档工程,在应用程序类的InitInstance()函数里LoadLibrary,里面有一个std::vector< IFunctionExtensionPtr> m_FuncExts用于保存所有模块,然后单击一个停靠栏的一个支项来弹出DLL中的对话框。现在麻烦的是底层的调用机制我也不是很清楚。
zyyoung 2008-03-08
  • 打赏
  • 举报
回复
多数原因是domodal失败,可以给dlg换个资源id
yxz_lp 2008-03-08
  • 打赏
  • 举报
回复
应该不是SP1的BUG。

//这句也不会出现断言失败呀,只会调试输出警告
#ifdef _DEBUG
if ( AfxGetApp()-> IsKindOf( RUNTIME_CLASS( COleControlModule ) ) )
{
TRACE(traceAppMsg, 0, "Warning: Creating dialog from

within a COleControlModule application is not a supported scenario.\n");
}
#endif


你这是个扩展Dll,不用切换模块,还是找出具体是哪句断言失败
cnzdgs 2008-03-08
  • 打赏
  • 举报
回复
我的VS2005没装SP1是这样的,没找到那些代码。
BOOL CWnd::CreateDlgIndirect(LPCDLGTEMPLATE lpDialogTemplate,
CWnd* pParentWnd, HINSTANCE hInst)
{
ASSERT(lpDialogTemplate != NULL);
if (pParentWnd != NULL)
ASSERT_VALID(pParentWnd);

if(!hInst)
hInst = AfxGetResourceHandle();

#ifndef _AFX_NO_OCC_SUPPORT
_AFX_OCC_DIALOG_INFO occDialogInfo;
COccManager* pOccManager = afxOccManager;
#endif

HGLOBAL hTemplate = NULL;

HWND hWnd = NULL;
#ifdef _DEBUG
DWORD dwError = 0;
#endif

TRY
{
VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG));
AfxDeferRegisterClass(AFX_WNDCOMMCTLSNEW_REG);

#ifndef _AFX_NO_OCC_SUPPORT
// separately create OLE controls in the dialog template
if (pOccManager != NULL)
{
if (!SetOccDialogInfo(&occDialogInfo))
return FALSE;

lpDialogTemplate = pOccManager->PreCreateDialog(&occDialogInfo,
lpDialogTemplate);
}

if (lpDialogTemplate == NULL)
return FALSE;
#endif //!_AFX_NO_OCC_SUPPORT

// If no font specified, set the system font.
CString strFace;
WORD wSize = 0;
BOOL bSetSysFont = !CDialogTemplate::GetFont(lpDialogTemplate, strFace,
wSize);

if (afxData.bWin95 && !bSetSysFont && GetSystemMetrics(SM_DBCSENABLED))
{
bSetSysFont = (strFace == _T("MS Shell Dlg"));
if (bSetSysFont && (wSize == 8))
wSize = 0;
}

if (bSetSysFont)
{
CDialogTemplate dlgTemp(lpDialogTemplate);
dlgTemp.SetSystemFont(wSize);
hTemplate = dlgTemp.Detach();
}

if (hTemplate != NULL)
lpDialogTemplate = (DLGTEMPLATE*)GlobalLock(hTemplate);

// setup for modal loop and creation
m_nModalResult = -1;
m_nFlags |= WF_CONTINUEMODAL;

// create modeless dialog
AfxHookWindowCreate(this);
hWnd = ::CreateDialogIndirect(hInst, lpDialogTemplate,
pParentWnd->GetSafeHwnd(), AfxDlgProc);
#ifdef _DEBUG
dwError = ::GetLastError();
#endif
}
CATCH_ALL(e)
{
DELETE_EXCEPTION(e);
m_nModalResult = -1;
}
END_CATCH_ALL

#ifndef _AFX_NO_OCC_SUPPORT
if (pOccManager != NULL)
{
pOccManager->PostCreateDialog(&occDialogInfo);
if (hWnd != NULL)
SetOccDialogInfo(NULL);
}
#endif //!_AFX_NO_OCC_SUPPORT

if (!AfxUnhookWindowCreate())
PostNcDestroy(); // cleanup if Create fails too soon

// handle EndDialog calls during OnInitDialog
#ifdef _DEBUG
#ifndef _AFX_NO_OCC_SUPPORT
DWORD dwOldFlags = m_nFlags;
#endif
#endif
if (hWnd != NULL && !(m_nFlags & WF_CONTINUEMODAL))
{
::DestroyWindow(hWnd);
hWnd = NULL;
}

if (hTemplate != NULL)
{
GlobalUnlock(hTemplate);
GlobalFree(hTemplate);
}

// help with error diagnosis (only if WM_INITDIALOG didn't EndDialog())
if (hWnd == NULL)
{
#ifdef _DEBUG
#ifndef _AFX_NO_OCC_SUPPORT
if (dwOldFlags & WF_CONTINUEMODAL)
{
if (afxOccManager == NULL)
{
TRACE(traceAppMsg, 0, ">>> If this dialog has OLE controls:\n");
TRACE(traceAppMsg, 0, ">>> AfxEnableControlContainer has not been called yet.\n");
TRACE(traceAppMsg, 0, ">>> You should call it in your app's InitInstance function.\n");
}
else if (dwError != 0)
{
TRACE(traceAppMsg, 0, "Warning: Dialog creation failed! GetLastError returns 0x%8.8X\n", dwError);
}
}
#endif //!_AFX_NO_OCC_SUPPORT
#endif //_DEBUG
return FALSE;
}

ASSERT(hWnd == m_hWnd);
return TRUE;
}
clever101 2008-03-08
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 cnzdgs 的回复:]
不知道是不是SP1的Bug,我没装SP1。
[/Quote]

大侠,你看看你的没装sp1的有没有下面这段代码:

#ifdef _DEBUG
if ( AfxGetApp()-> IsKindOf( RUNTIME_CLASS( COleControlModule ) ) )
{
TRACE(traceAppMsg, 0, "Warning: Creating dialog from

within a COleControlModule application is not a supported scenario.\n");
}
#endif
cnzdgs 2008-03-08
  • 打赏
  • 举报
回复
你把RestoreResourceHandle函数改一下:
AfxGetModuleState()->m_hCurrentResourceHandle = LoadLibrary();
这样试试。
clever101 2008-03-08
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 hwsts2 的回复:]
DoModal() CreateDlgIndirect()
常试把他们2个重载了 然后

把那段代码删除了

[/Quote]

把CreateDlgIndirect() 重载后,出现很多错误:
lg.cpp(65) : error C2065: “AFX_WNDCOMMCTLS_REG”: 未声明的标识符
1>e:\titanplatformsdk\highspec\otalternatextract\alterextractdlg.cpp(65) : error C3861: “AfxDeferRegisterClass”: 找不到标识符
1>e:\titanplatformsdk\highspec\otalternatextract\alterextractdlg.cpp(66) : error C2065: “AFX_WNDCOMMCTLSNEW_REG”: 未声明的标识符
1>e:\titanplatformsdk\highspec\otalternatextract\alterextractdlg.cpp(66) : error C3861: “AfxDeferRegisterClass”: 找不到标识符
1>e:\titanplatformsdk\highspec\otalternatextract\alterextractdlg.cpp(86) : error C2653: “CDialogTemplate”: 不是类或命名空间名称

它要用到很多内部宏定义,显然这不是一个好办法。
clever101 2008-03-08
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 zyyoung 的回复:]
多数原因是domodal失败,可以给dlg换个资源id
[/Quote]

在Resource.h中原来对话框的资源ID

#define IDD_ALTEREXT 6002

我将其改为
#define IDD_ALTEREXT 10002

然后单步调试进去:
INT_PTR CDialog::DoModal()
{
// can be constructed with a resource template or InitModalIndirect
ASSERT(m_lpszTemplateName != NULL || m_hDialogTemplate != NULL ||
m_lpDialogTemplate != NULL);

// load resource as necessary
LPCDLGTEMPLATE lpDialogTemplate = m_lpDialogTemplate;
HGLOBAL hDialogTemplate = m_hDialogTemplate;
HINSTANCE hInst = AfxGetResourceHandle();
if (m_lpszTemplateName != NULL)
{
hInst = AfxFindResourceHandle(m_lpszTemplateName, RT_DIALOG);
HRSRC hResource = ::FindResource(hInst, m_lpszTemplateName, RT_DIALOG);
hDialogTemplate = LoadResource(hInst, hResource);
}
if (hDialogTemplate != NULL)
lpDialogTemplate = (LPCDLGTEMPLATE)LockResource(hDialogTemplate);

// return -1 in case of failure to load the dialog template resource
if (lpDialogTemplate == NULL)
return -1; // 程序在这里退出,这说明lpDialogTemplate == NULL,这是为什么呢?
clever101 2008-03-08
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 yxz_lp 的回复:]
应该不是SP1的BUG。


你这是个扩展Dll,不用切换模块,还是找出具体是哪句断言失败
[/Quote]

大虾,你说得有道理,我又单步调试了一下,发现在在下面出错:
BOOL CObject::IsKindOf(const CRuntimeClass* pClass) const
{
ENSURE(this != NULL); // 在这一步出错
// it better be in valid memory, at least for CObject size
ASSERT(AfxIsValidAddress(this, sizeof(CObject)));

// simple SI case
CRuntimeClass* pClassThis = GetRuntimeClass();

ENSURE(pClassThis);
return pClassThis->IsDerivedFrom(pClass);
}


ENSURE(this != NULL); // 在这一步出错,这说明this指针为空,这是为什么呢?
cnzdgs 2008-03-08
  • 打赏
  • 举报
回复
不知道是不是SP1的Bug,我没装SP1。
clever101 2008-03-08
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 jhs1982419 的回复:]
看下是不是标准的问题,采用哪种方式调用.标准C++还是什么。
[/Quote]

这跟函数调用方式没有关系吧。是dll内部出现的问题。
clever101 2008-03-08
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 cnzdgs 的回复:]
你用Release编译有问题吗?2005的Release也是可以调试的。
[/Quote]

别人给我的是第三方库是debug版,现在很难办,无法编译release版的。这个到底是不是VS C++2005 + sp1的bug啊!
加载更多回复(5)

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧