DrGraph软件升级:处理BUG_退出程序出错

简要说明

  1. 退出程序出错(解决1/2)

提交人

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

定位及调试过程

  1. 经查,初步定为释放DLL对象时出错
  1. 加上日志输出

__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);

        }

    }

}

打开日志开关

  1. 查看程序退出时的日志输出

<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" />

  1. 说明这里没错,继续跟踪,发现是ClearCbwGraphForm的问题,更进一步,定位在SpecialDebugInfo

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已被自动释放掉,而此时再调用时将会出错

  1. 修改:

删除ClearCbwGraphForm()中的

    CBW_LOG(SpecialDebugInfo(), qdtProgram);

不再输出该日志信息。

  1. 结果状态:此处通过,还是会出现该提示对话框

    检查日志记录到:

    <Info msg="退出工作: delete OperateNames" />

    <Info msg="退出工作: after delete OperateNames" />

    跟踪发现调用~TVariantT后出问题,其构造析构函数调用次数很多,下面跟一下

构造

析构

:008DFCCC

 

:0012FAC4 { "http://127.0.0.1" }

 

:0012FA7C

 

:0012FA6C

 

:0012FA5C

 

:0012FA8C

 
 

:0012FA5C

 

:0012FA6C

 

:0012FA7C

 

:0012FA8C

 

:0012FAC4

:0012FB28 { "D:\\ExenObj\\Exe\\2010Graph\\welcome\\index.html" }

 

:0012FAE0

 

:0012FAD0

 

:0012FAC0

 

:0012FAF0

 
 

:0012FAC0

 

:0012FAD0

 

:0012FAE0

 

:0012FAF0

 

:0012FB28

:0012FA20 { "D:\\ExenObj\\Exe\\2010Graph\\welcome\\index.html" }

 

:0012F9D8

 

:0012F9C8

 

:0012F9B8

 

:0012F9E8

 
 

:0012F9B8

 

:0012F9C8

 

:0012F9D8

 

:0012F9E8

 

:0012FA20

 

:008DFCCC

完全匹配

运行之后提示出错

但不在IDE下运行是正常的

 
  1. 屏蔽掉退出宏#pragma exit

#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

原文地址:https://www.cnblogs.com/drgraph/p/3036782.html