• 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

  • 相关阅读:
    mysql常用技巧
    java中集成CKEditor和CKFinder
    Linux_C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区
    Linux_内存分配中的堆和栈
    mysql中的text,mediumtext,longtext在Hibernate中的类型映射
    循环神经网络LSTM RNN回归:sin曲线预测
    什么?语音合成开源代码不会跑,follow me!
    华为云GaussDB:发挥生态优势,培养应用型DBA
    对话华为云专家,摆脱无意义“内卷”
    带你读AI论文丨用于细粒度分类的Transformer结构—TransFG
  • 原文地址:https://www.cnblogs.com/drgraph/p/3036782.html
Copyright © 2020-2023  润新知