简要说明 |
|
提交人 |
DrGraph 2013/04/22 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
处理状态 |
处理中 |
同步状态 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
现象 |
退出程序,出现错误: 详细信息: 问题签名: 问题事件名称: APPCRASH 应用程序名: DrGraph.exe 应用程序版本: 0.0.0.0 应用程序时间戳: 00000000 故障模块名称: ntdll.dll 故障模块版本: 6.1.7600.16385 故障模块时间戳: 4a5bdadb 异常代码: 80000003 异常偏移: 0009f8d2 OS 版本: 6.1.7600.2.0.0.256.1 区域设置 ID: 2052 其他信息 1: d1ab 其他信息 2: d1ab624ec7d094c26a73530c245a3468 其他信息 3: d1ab 其他信息 4: d1ab624ec7d094c26a73530c245a3468 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
定位及调试过程 |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
__fastcall TqaDllBase::~TqaDllBase() { CBW_LOG(THelper::FormatString("准备:释放动态链接库 %s", FDllFileName.c_str()), qdtInterface); if (FDeleteDllModel && FDllModelObject) { try { FDeleteDllModel(FDllModelObject); CBW_LOG("成功:删除接口对象", qdtInterface); } catch(Exception & ex) { CBW_LOG(THelper::FormatString("失败:释放动态链接库 %s 时出错:%s", FDllFileName.c_str(), ex.Message.c_str()), qdtInterface); } } if (hDll) { FDllCount[hDll] -= 1; if (FDllCount[hDll] == 0) try { FreeLibrary((HMODULE)hDll); CBW_LOG(THelper::FormatString("成功:释放动态链接库 %s", FDllFileName.c_str()), qdtInterface); } catch(Exception & ex) { CBW_LOG(THelper::FormatString("失败:释放动态链接库 %s 出现异常 %s", FDllFileName.c_str()), qdtInterface); } } } |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
打开日志开关 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Info msg="准备:释放动态链接库 D:\ExenObj\Exe\2010Graph\dll\QaWord.dll" /> <Info msg="成功:删除接口对象" /> <Info msg="成功:释放动态链接库 D:\ExenObj\Exe\2010Graph\dll\QaWord.dll" /> <Info msg="准备:释放动态链接库 D:\ExenObj\Exe\2010Graph\dll\CbwRegExp.dll" /> <Info msg="成功:删除接口对象" /> <Info msg="成功:释放动态链接库 D:\ExenObj\Exe\2010Graph\dll\CbwRegExp.dll" /> <Info msg="准备:释放动态链接库 D:\ExenObj\Exe\2010Graph\dll\CbwImage.dll" /> <Info msg="成功:删除接口对象" /> <Info msg="成功:释放动态链接库 D:\ExenObj\Exe\2010Graph\dll\CbwImage.dll" /> <Info msg="准备:释放动态链接库 D:\ExenObj\Exe\2010Graph\dll\QaVoice.dll" /> <Info msg="成功:删除接口对象" /> <Info msg="成功:释放动态链接库 D:\ExenObj\Exe\2010Graph\dll\QaVoice.dll" /> <Info msg="准备:释放动态链接库 D:\ExenObj\Exe\2010Graph\dll\QaUtil.dll" /> <Info msg="成功:删除接口对象" /> <Info msg="成功:释放动态链接库 D:\ExenObj\Exe\2010Graph\dll\QaUtil.dll" /> |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
UnicodeString __fastcall SpecialDebugInfo() { int size = AllCompilerObjects.size(); UnicodeString result = THelper::FormatString("共有 %d 个分析对象:", size); // * std::map<int, TCbwCompilerObject*>aAllCompilerObjects; CBW_ITERATOR_MAP(TCbwCompilerObject*, int, AllCompilerObjects) aAllCompilerObjects[it->second] = it->first; CBW_ITERATOR_MAP(int, TCbwCompilerObject *, aAllCompilerObjects) { TCbwCompilerObject * object = it->second; UnicodeString refCount = ""; TEquation_Variable * ev = dynamic_cast<TEquation_Variable*>(object); if (ev) refCount.sprintf(L", 引用次数: %d", ev->RefCount); try { result += THelper::FormatString("\n下标:%d, 地址:%x, 类型:%s, 信息:%s%s", it->first, int(object), UnicodeString(object->ClassName()).c_str(), object->Content.c_str(), refCount.c_str()); } catch(Exception & ex) { result += EXCEPTION_INFO + THelper::FormatString ("\n下标:%d(Exception: %s), 类型:%s", it->first, ex.Message.c_str(), UnicodeString(object->ClassName()).c_str()); } } // */ return result; } 最终原因在于:程序关闭退出时,AllCompilerObjects已被自动释放掉,而此时再调用时将会出错 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
删除ClearCbwGraphForm()中的 CBW_LOG(SpecialDebugInfo(), qdtProgram); 不再输出该日志信息。 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
完全匹配 运行之后提示出错 但不在IDE下运行是正常的 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#pragma exit GlobalExitWork 64 #pragma exit DeleteMVCCriticalSection 64 #pragma exit FreeAllDllObjects 64 #pragma exit DeleteOperateItemNameList 64 #pragma exit ClearCbwTreeObject 80 #pragma exit DestroyGlobalXMLNode 70 #pragma exit DestroyDefaultVclClasses 70 #pragma exit ClearCbwGraphForm 80 #pragma exit ClearCbwObject 80 #pragma exit DestroyObjectTypeList 80 #pragma exit DestoryExecuteXML 70 #pragma exit DestoryUDPObject 80 之后,程序退出正常 逐个添加上: #pragma exit GlobalExitWork 64 à OK #pragma exit DeleteMVCCriticalSection 64 à OK #pragma exit FreeAllDllObjects 64 à Error #pragma exit DeleteOperateItemNameList 64 à OK #pragma exit ClearCbwTreeObject 80 à OK #pragma exit DestroyGlobalXMLNode 70 à OK #pragma exit DestroyDefaultVclClasses 70 à OK #pragma exit ClearCbwGraphForm 80 à OK #pragma exit ClearCbwObject 80 à OK #pragma exit DestroyObjectTypeList 80 à OK #pragma exit DestoryExecuteXML 70 à OK #pragma exit DestoryUDPObject 80 à OK 问题定位为FreeAllDllObjects 输出日志,发现共有5个DLL: D:\ExenObj\Exe\2010Graph\dll\QaWord.dll D:\ExenObj\Exe\2010Graph\dll\CbwRegExp.dll D:\ExenObj\Exe\2010Graph\dll\CbwImage.dll D:\ExenObj\Exe\2010Graph\dll\QaVoice.dll D:\ExenObj\Exe\2010Graph\dll\QaUtil.dll 逐个屏蔽DLL __fastcall TqaDllBase::~TqaDllBase() { static int count = 0; if(++count == N) return; … } 经查,排列屏蔽,发现,任意一个DLL卸载均会导致最终抛出对话框。 再进一步,发现屏蔽FreeLibrary即可。 什么原因? 之前声明hDll为HANDLE类型,中间会强制转换为HMODULE,不会是这个原因吧? 改成HMODULE类型,运行还是出错。 现在唯一的解释就是:DLL是用AnsiString实现的,宿主程序是用UnicodeString。但这明显是说不通的。 另一个解释就是:DLL是用CB6实现的,宿主程序是用CB2010实现的。之前在CB6中不会出错。 越解释越不通,暂且放下。屏蔽掉FreeLibrary |