zoukankan      html  css  js  c++  java
  • HEAP[xxx.exe]:Invalid Address specified to RtlValidateHeap 错误的解决方法总结

    一、情况

    抽象出问题是这样的:

     

    class DLL_API1 A  

    {  

        func()  

        {  

            vector vec;  

            B b;  

            b.func(vec);  

            return TRUE;  

        }  

    }  

     

    其中B是另一个导出类,定义如下

    class DLL_API2 B  

    {  

    private:  

        vector m_vec;  

    public:  

        func( vector &vec )  

        {  

            vec = m_vec;  

        }  

    }  


     

    运行时发现,每次运行到A的return TRUE释放vector的时候,都会报错:user breakpoint called from code at  xxxxxxxxxxxxx,并在Debug的提示框中出现:

    HEAP[xxx.exe]:Invalid Address specified to RtlValidateHeap    的提示。

    网上查了下,基本上都是说是dll和exe在不同的地方开辟了空间,在不同的地方释放的问题。看来以后还需要注意呢。

    解决的方法是:

    是外层被使用的内存,可以在外层定义后传参到非托管函数,在内部赋值后,在外层被调用,然后被释放;在内部被申请的空间,需在内部显式的的释放,避免造成内存泄露,这样就不会出现上述两种错误。(引用自:http://155134558.blog.163.com/blog/static/22278462009727103058451/

     

    也就是说可以做如下修改:

    1. class DLL_API1 A  
    2. {  
    3.     func()  
    4.     {  
    5.         B b;  
    6.         int nCnt = b.func1();  
    7.            
    8.         vector vec;  
    9.         b.func2(vec);  
    10.   
    11.         return TRUE;  
    12.     }  
    13. }  
    14.   
    15.    
    16.   
    17. class DLL_API2 B  
    18. {  
    19. private:  
    20.     vector m_vec;  
    21. public:  
    22.     int func1()  
    23.     {  
    24.         return m_vec.size();  
    25.     }  
    26.     func2( vector &vec )  
    27.     {  
    28.         vec = m_vec;  
    29.     }  
    30. }  


     

    不过目前这种解决方案看起来是比较挫啦,不知道能不能从设计上避免。这个问题就先放在这里吧。以后有更多经验的时候再回头看。

    二、情况

    遇到该问题的原因是,托管代码和非托管代码之间的分配机制不同,两者之间可以进行互操作,下面是查到的相关内容:

    经过一段时间对MSDN的钻研,终于明白C++/CLI互操作共分三种:

    1.P/Invoke

    2.Com interop

    3.C++ interop

    我想版主推荐的是指采用C++ interop方式。代码过程如下:

    1.将非托管结构和函数放在#pragmaunmanaged内,像这样

    #pragma unmanaged   

      

    struct cUserNestedStruct   

      

    {  

      

    .........  

      

    } ;  

      

    extern "C" int DllFunction(UserDefinedStruct**);  

    2. 然后,在托管代码中就可以直接调用了。

    #pragma  

      

    managed  

      

    int main()  

      

    {  

      

    UserDefinedStruct*   mystruct = new UserDefinedStruct();  

      

    int num = DLLFunction(&mystruct);  

      

    }  


     

    上述是调用Dll,进行互操作的情况。

    在我们的项目中,使用托管和非托管混合的方法,通过头文件,直接调用非托管程序。这里需要注意的是:托管代码的内存管理和非托管的内存管理是不同的。在内存堆的分配上也是不同的,所以,两者之间不能直接进行内存的互调用,例如:1,在非托管代码中不能释放托管代码申请的内存;

    2,在非托管代码中申请的内存,在函数结束后就被释放,如果被return到托管环境里,是无效的地址。

    是外层被使用的内存,可以在外层定义后传参到非托管函数,在内部赋值后,在外层被调用,然后被释放;在内部被申请的空间,需在内部显式的的释放,避免造成内存泄露,这样就不会出现上述两种错误。

    本项目中的问题是在非托管代码中,使用了对托管代码中内存块的一个引用,然后在函数结束时,被释放,这样就是free掉了托管代码中申请的内存,会报错,访问无效的内存。

    三、情况

    在编译的时候,exe和dll有可能链接的是静态的运行时库,也有可能链接的是dll版本的运行时库。如果在exe或者是dll中有一个链接的是静态的运行时库,那么就会存在两套内存分配的实例。所以在dll中申请的内存,到exe中释放就会失败,因为exe并不认识那块内存。解决的办法就是都使用dll版本的运行时库,这样,在进程空间内,只有一个运行时实例。

    四、情况

     

    WCHAR aPathname[]=L"\\c:\pbk_temp";  

    WCHAR aFilename[]=L"100.dat";  

    DWORD dwLimitedReadSize=0;  

    unsigned char* content;  

    content=NULL;  

              .......  

      

    dwResult = CONAReadFile(hFS, &FileInfo, content, dwLimitedReadSize, aPathname);  

             .........  

      

      

    delete [] content;  

    content=NULL;  


     

    CONAReadFile是Nokia提供的一个函数,原型为
    DWORD CONAReadFile(FSHANDLE hFSHandle, LPCONAPI_FILE_INFO pFileInfo, unsigned char** ppFileData, DWORD dwLimitedReadSize, const WCHAR* pstrTargetPath)

    现在我只要一执行delete [] content;程序就崩了。单步跟出现提示信息HEAP[PROPERTYSHEET.exe]: Invalid Address specified to RtlValidateHeap( 00A90000, 00197CC8 )

    这是怎么回事?该怎么解决。如果不delete会不会造成内存泄漏。

    原因:

    在Nokia的库中同时提供了释放char* content的方法,因为char* content指向的内存是由dll中的方法分配的,所以应该由dll中的方法释放。这正好符合C++关于谁分配,谁释放的准侧。
    从这个例子,我们可以看到,以后在写dll时,如果在dll中的某个方法内部分配了内存,同时要写一个释放该段内存的方法,对外公开,用来给外部的函数调用

    五、情况

    我封装了dll 原来是exe 现在封装成dll
    发现了这个错误 函数都执行没问题 就是函数执行完 就爆这个错误
    我没用dll什么的 就用了string 

    调用是

    void CTestDlg::OnButton1()    

    {      

        // TODO: Add your control notification handler code here       

        UpdateData(TRUE);       

        string ts = m_text;       

        string sData = _ConvertHextoCString(ts);         

        AfxMessageBox(sData.c_str());     

    }   


    dll封装函数是

    #include "stdafx.h"   

    #include <string>   

    using namespace std;     

    BOOL APIENTRY DllMain( HANDLE hModule,   DWORD  ul_reason_for_call, LPVOID lpReserved)   

    {       

        return TRUE;   

    }   

    string ConvertHextoString(string hex)   

    {       

        string result;       

        char temp[3];       

        int i = 0;       

        int nLen = hex.length();       

        if (nLen%2 != 0)       

        {           

            return "ERROR";       

        }                

        return result;  

    }  


    问题解决了 封装dll 最好类型不要用string 这样很容易有问题
    还有就是在传入参数 加上const这样 就保证不会有问题了

    六、情况

    Dll之间由于由于空间分配和删除引起的

    invalid address specified to rtlvalidateheap

    在外层模块中定义了一个变量,传入内层模块赋值,用完后在外层模块释放时出错。

    一个可能的原因:

    在不同模块(工程)之间传递 C++ 类,而这两个模块用了不同的运行时库(Runtime Library)设置

    例如:EXE 模块调用 DLL 模块里传递 C++ 类的函数,但 DLL 模块使用静态链接(Release 是 Multi-threaded (/MT)、Debug 是 Multi-threaded Debug (/MTd))方式编译,而 EXE 模块使用动态链接(Release 是 Multi-threaded DLL (/MD)、Debug 是 Multi-threaded Debug DLL (/MDd))方式编译。

    可以对比这两个模块的工程属性 - C/C++ - Code Generation - Runtime Library,看看设置是否一样,如果不一样要改成一样的。

    如果无法解决问题,那就是别的原因了。

    七、情况

    析构函数出问题

    调试信息:

    HEAP[MHPSO.exe]: Invalid Address specified to RtlValidateHeap( 00390000, 00DAAC68 )
    Windows 已在 MHPSO.exe 中触发一个断点。

    其原因可能是堆被损坏,这说明 MHPSO.exe 中或它所加载的任何 DLL 中有 Bug。

    一般是野指针导致。

    八、

    转载自: http://www.bhcode.net/article/20100713/12048.html

    //微粒类  

    class PARTICLE  

    {  

    public:  

        double *X;      //微粒的坐标数组  

        double *V;      //微粒的速度数组  

        double *XBest;  //微粒的最好位置数组  

        int Dim;        //微粒的维数  

        double Fit;     //微粒适合度  

        double FitBest; //微粒最好位置适合度  

      

      

        //构造函数  

        PARTICLE();     //空构造函数  

        PARTICLE(int n);//维数为参数的构造函数  

        //析构函数  

        ~PARTICLE();  

        void SetDim(int d); //设置微粒的维数  

    };      

      

    //微粒构造函数  

    PARTICLE::PARTICLE() //空构造函数  

    {  

        X = 0; V = 0; XBest = 0; Dim = 0;  

    }    

    PARTICLE::PARTICLE(int n) //维数为参数的构造函数  

    {  

        if(n<0)   

        {  

            cout<<"输入有错,维数必须大于0"<<endl;  

            return;  

        }  

        Dim = n;  

        X = new double[Dim];  

        V = new double[Dim];  

        XBest = new double[Dim];  

    }    

      

    //微粒析构函数  

    PARTICLE::~PARTICLE()  

    {  

        if(Dim)  

        {  

            delete X;  

            delete V;  

            delete XBest;  

            X=0;  

            V=0;  

            XBest=0;  

        }  

    }  

            

    //定义群粒子类  

    class PSO  

    {  

    public:  

        PARTICLE * Particle;    //微粒群数组  

        int PNum;               //微粒个数  

        int GBestIndex;         //最好微粒索引  

        double W;               //惯性权重  

        double C1;              //加速度系数1  

        double C2;              //加速度系数2  

        double *Xup;            //微粒坐标上界数组  

        double *Xdown;          //微粒坐标下界数组  

        double *Vmax;           //微粒最大速度数组    

     

        void Initialize();      //初始化群体  

        void CalFit();          //计算全体适合度  

        virtual void ParticleFly(); //微粒飞翔,产生新一代微粒   

        //通讯函数,返回值为false时,系统停止优化  

        bool (*Com)(double,     //最优微粒适合度  

        double*,                //最优微粒坐标数组  

        double**,               //所有微粒坐标指针数组  

        int);                   //当前最优微粒索引  

        

        

        //构造函数  

        PSO(); //空构造函数  

        PSO(int dim, //微粒维数  

        int num); //微粒个数  

        //析构函数  

        ~PSO();  

    };    

      

      

    //PSO构造函数  

    PSO::PSO()  

    {  

        Particle = 0;  

        PNum = 0;  

        GBestIndex = 0;  

        Xup = 0;  

        Xdown = 0;  

        W = 1;  

        C1 = 2;  

        C2 = 2;  

        Com = 0;  

    }  

      

      

    PSO::PSO(int dim, int num)  

    {  

        if(dim<0 || num <0)   

        {  

            cout<<"输入有错,维数和粒子个数必须大于0"<<endl;  

            return;  

        }  

      

      

        Particle = new PARTICLE[num];  

        for(int i=0; i< num; i++)   

            Particle[i].SetDim(dim);  

        PNum = num;  

        GBestIndex = 0;  

        Xup = new double[dim];  

        Xdown = new double[dim];  

        Vmax = new double[dim];  

        W = 1;  

        C1 = 2;  

        C2 = 2;  

        Com = 0;  

    }  

      

       

    //析构函数  

    PSO::~PSO()  

    {  

        if(Particle)   

            delete []Particle;  

        if(Xup)   

            delete []Xup;//位置上界  

        if(Xdown)   

            delete []Xdown;//位置下界  

        if(Vmax)   

            delete []Vmax; //速度上下界  

        Xup = 0;  

        Xdown = 0;  

        Vmax = 0;  

        Particle=0;  

    }    

        

    //派生多种群分层的PSO类  

    class MHPSO   

    {  

    public:  

        PSO** FirstPso; //第一层多种群粒子群的指针的指针  

        int L; //第一层种群的个数 = 第二层粒子群中粒子的个数   

        double C3; //加速度系数3  

        PSO* SecondPso;//第二层的粒子群指针  

        HANDLE wMutex;  

        double Vmin[20] ; //当粒子飞行速度小于Vmin的时,速度变化已不能更新粒子的位置,重新初始化速度  

    public:  

        MHPSO()  

        {  

            FirstPso=0; L=0; SecondPso=0; C3 = 2;  

            for(int i=0;i<20;i++)  

            Vmin[i] = 0.0001 ;  

            wMutex = ::CreateMutex(NULL,false,NULL);  

        }  

      

    //构造函数,给出微粒维数n 和种群个数L,种群中粒子的个数m  

    MHPSO(int n, int m,int L)  

    {  

        this->L = L;  

        FirstPso = new PSO*[L];  

        for(int i=0 ;i< L;i++)  

            FirstPso[i] = new PSO(n,m);  

        

        SecondPso = new PSO(n,L);   

        C3 = 2;  

        for(int i=0;i<20;i++)  

            Vmin[i] = 0.0001 ;  

        wMutex = ::CreateMutex(NULL,false,NULL);  

    }     

      

    ~MHPSO()  

    {  

        for(int i=0;i<L;i++)  

        {  

            delete this->FirstPso[i];  

            this->FirstPso[i] =0;  

        }  

      

        delete []FirstPso;  

        this->FirstPso = 0;  

        delete SecondPso;   

        SecondPso =0; //这两句有问题。。。,如果去掉程序就不会出错。。  

        ::CloseHandle(wMutex);  

    }    

    };   

  • 相关阅读:
    POJ 2976 Dropping tests
    【学习笔记-中国剩余定理】POJ1006 Biorhythms
    2017.10.6北京清北综合强化班DAY6
    P1607 [USACO09FEB]庙会班车Fair Shuttle
    2017.10.5北京清北综合强化班DAY5
    洛谷 P1379 八数码难题
    A. 拼音魔法
    A
    K
    A
  • 原文地址:https://www.cnblogs.com/blogofwu/p/4390564.html
Copyright © 2011-2022 走看看