void GetDesJSharp(char src[], char key[], LPTSTR des, bool EnDe)
{
char* buf = new char[256];
char* bufout =new char[256];
ZeroMemory(buf,256);
ZeroMemory(bufout,256);
if(EnDe)
{
buf = StrToHex(src);
bufout = encrypt(buf,key,EnDe);
}
else
{
buf = encrypt(src,key,EnDe);
bufout = HexToStr(buf);
}
ZeroMemory(des,256);
memcpy(des,bufout,strlen(bufout)); //内存泄漏
//delete[] buf;
//delete[] bufout;
}
这个函数中有两个char*,当我使用delete释放内存时就出错,如果不用delete又存在内存泄漏,该怎么办?

解决方案 »

  1.   

    从你的代码来看,buf、bufout都用从其它函数(StrToHex、encrypt)返回的指针赋值了,那么前面new出来的就成了野指针。也就是说,不需要new。
    而从函数返回的指针,是否需要delete,得看具体这个函数是否需要你detele。
    另外,LPTSTR没有指示大小的参数配合,也没有地方来判断是否越界,最后这个ZeroMemory、memcpy函数都存在溢出的危险。
      

  2.   

        char* buf = new char[256];
        char* bufout =new char[256];
    只给声明就行了,分配出来的内存没用上而且delete时的指针地址并非分配到的内存的地址
      

  3.   

    里面只char buf [256]
    bufout [256]定义在栈上,不久行了,干嘛new?
      

  4.   

    new不是这样用的,new的目的是动态分配,你大小都已经确定了,没必要new了。
      

  5.   

    你的这两个函数(StrToHex、encrypt)中如果已经申请了内存,那在你的外层函数中就不用了再new了。使用指针就可以。像这样 char *buf;如果你这两个函数中没有动态申请内存,你在外面还获得到相应的值?建议看看内存使用的一些基础。
      

  6.   

    内存使用错误了!! 就算能delete也是泄漏!!
      

  7.   

    谢谢大家,确实需要补课。
    StrToHex、encrypt中都没有申请内存,都是参数传入的。
      

  8.   


    void GetDesJSharp(char src[], char key[], LPTSTR des, bool EnDe)
    {
    //char* buf = new char[256];
    //char* bufout =new char[256];
    char* buf;
    char* bufout;
    //char buf[256];
    //char bufout[256];
    //ZeroMemory(buf,256);
    //ZeroMemory(bufout,256);
    if(EnDe)
    {
    buf = StrToHex(src);
    bufout = encrypt(buf,key,EnDe);
    }
    else
    {
    buf = encrypt(src,key,EnDe);
    bufout = HexToStr(buf);
    }
    //ZeroMemory(des,256);
    memcpy(des,bufout,strlen(bufout)); //内存泄漏
    //delete[] buf;
    //delete[] bufout;
    }
    哈哈,解决了。
    内存申请的问题都主存函数的外部,也就是调用都申请内存。
      

  9.   

    内存申请的问题都放在函数的外部,也就是调用者申请内存。
    .............
    有点高兴。另外,LPTSTR没有指示大小的参数配合,也没有地方来判断是否越界,最后这个ZeroMemory、memcpy函数都存在溢出的危险。现在就剩下memcpy越界存在溢出的可能,暂时放在调用时统一约定长度,这个与StrToHex、encrypt也有关。
      

  10.   

    楼主的解决方法是不好的方法,在大的程序中,你将会发现,问题多多地出现,因为没有人会注意到你的StrToHex()和encrypt()中会申请内存而让外面的代码去删除这些申请了的内存,再者,里面申请内存的大小,外面不知道,所以是很危险的做法好的做法是,修改两个函数,他们都至少多加一个参数,把buf和bufout做为参数传入,而它们的内存申请,则是楼主给的代码即可,即在楼主的代码里,只需要修改两个子函数即可,不要使用返回值的形式就行了,这样的代码清晰明了,内存的申请和销毁,尽量保证在一个函数内进行,而不要跨函数
      

  11.   


    StrToHex()没有申请内存;
    encrypt()中得时申请的内存都在函数返回前销毁了;
    StrToHex()返回的指针是传入的参数;
    encrypt()返回的指针是个类中共用的char ch[256];
    这个程序问题确实很多,待我再研究研究
      

  12.   

    是指这两个函数StrToHex()和encrypt()不要用return吧?
    改改,呵呵
      

  13.   

    现在我总算解决了以前的一个疑惑,VC自带的函数很少用return来返回值,return一般返回一个int、DWORD、BOOL作为程序返回结果的参考,而真正需要的返回结果一般都用参数返回,可能就是这方面的原因吧......
      

  14.   

    我曾经编过画Bezier曲线的程序,里面也有同样的问题,分步执行到delte时就有异常,看过各位的回贴,确实访好好学习。
      

  15.   


    我按你所说的方法改了整个函数及类,现在在C++ 环境中调用Dll没有问题,可是如果用C#项目调用就不行了。下面是出错信息:未处理的“System.AccessViolationException”类型的异常出现在 DLLTESTC.exe 中。其他信息: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
      

  16.   

    未处理的“System.AccessViolationException”类型的异常出现在 DLLTESTC.exe 中。 
    其他信息: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。 
    ----------------------------------------------------------------------------
    把你的代码贴出来。可能的情况:
    1. 你的类没有修改好,内部有问题没有处理,比如越界
    2. 你在调用它时,缓冲区不正确,指向了不可写的内存区
    3. 你在调用 它时,使用了野指针
    4. unicode造成了越界,而你没有注意到。即你的dll使用了unicode,而C#使用了ansi,所以当你传入了认为是8个字节的缓冲区时,在dll中可能认为是8个字符(16个字节),此时你拷贝进去超过8个字节的内容时越界
    5. 你拷贝操作时的源字符串缓冲区没有以'\0'结尾致使其后面带了很长的字符串造成了越界
      

  17.   

    我用StringBuilder调用没有问题。
    准备自己再检查你所说的几点。
    谢谢!
      

  18.   

    问题应该与strcpy_s有关:char p_str[STR_LEN];char* encrypt(char pw[],char key[],bool jiami,char pwout[STR_LEN])
    {
        ZeroMemory(pwout,STR_LEN);//返回值初始化 STR_LEN=260
        char tt[STR_LEN];
        
        .......    strcpy_s(p_str, tt);//这行不出错,
        strcpy_s(pwout, tt);//这行编译能不过,说不能用2个参数
        strcpy_s(p_str,strlen(tt), tt);//这个地方变换多种格试置换也不行,L(Buffer too small...
        strcpy_s(p_str,_countof(tt), tt);//编译没有问题,C#调用时不能用string作参数
        return p_str;//
    }
    好象用strcpy还只有警告而不出错。另:出错类型与C#调用时的参数的数据类型关系很大,string出错,StringBiulder、IntPtr不出错,BSTR好象也能用
      

  19.   

    char* encrypt(char pw[],char key[],bool jiami,char pwout[STR_LEN])
    {
        ZeroMemory(pwout,STR_LEN);//返回值初始化 STR_LEN=260
        char tt[STR_LEN];
        
        .......
    ----------------------------------------------------------------------
    我觉得这样写不大好,习惯于这样写:
    char* encrypt(char *pw,char *key,bool jiami,char *pwout, long lenoutbuf)
    {
        ZeroMemory(pwout,lenoutbuf);//返回值初始化 STR_LEN=260
        char *ptt = new char[lenoutbuf];
        
        .......另外,strcpy_s()要求具体的参数长度,而且这样修改之后,应该就可以编译通过了
      

  20.   

    strcpy_s()
    问题就在这个上面,第三个参数用const char*或char []可以,用char*不行;
    第二个参数用_countof()获取整个数组的元素可以,用strlen或其他int变量包括常量都可能出错;
    可是_countof是整个数组元素个数啊,会影响效率吧?通过几天的反复测试,觉得问题的关键是:
    1、中间的Buffer用什么类型过度;
    2、传出参数时用什么函数,memcpy还是strcpy,strcpy是肯定没有出错,但有个编译警告,memcpy和strcpy_s都有出错的情况;
      

  21.   

    问题原因找到了,strlen(ch)返回的是ch中从0到'\0'的字符的个数,这个长度不含'\0';所以strcpy_s(p_str,strlen(tt), tt);会出错,改成strcpy_s(p_str,strlen(tt)+1, tt);就通过了。
    这算不算是VS2005的一个Bug?我觉得函数strcpy_s既然有参数_DstSize,就应该用它检查数据的正确与否,当_DstSize,小于_Dst的大小(长度)时,应该版对_DstSize+1置'\0'。
      

  22.   

    void GetDesJSharp(char src[], char key[], LPTSTR des, bool EnDe)
    {
        char* buf = NULL;//new char[256];
        char* bufout =NULL;//new char[256];
        //ZeroMemory(buf,256);
        //ZeroMemory(bufout,256);
        if(EnDe)
        {
            buf = StrToHex(src);//查看这个函数的调用规约        bufout = encrypt(buf,key,EnDe);//查看这个函数的调用规约    }
        else
        {
            buf = encrypt(src,key,EnDe);//查看这个函数的调用规约        bufout = HexToStr(buf);//查看这个函数的调用规约    }
        ZeroMemory(des,256);
        memcpy(des,bufout,strlen(bufout));    //内存泄漏
        //delete[] buf;
        //delete[] bufout;
    }
      

  23.   

    现在关键是strcpy_s的问题,MSDN对第二个参数的解释是Size of the destination string buffer.在我看来要这个参数没有意义!!!!!!!!!!!!!
    我编程是肯定要考虑目标参数能不能容纳下源,虽然这个错误是会出,但这不应该是开发平台解决的问题,它应该解决我们合理的参数不出错。哎,不懂英语,不然早就发现问题并解决了
      

  24.   

    这个问题不再在本贴讨论,本贴的内存泄漏的问题前面几位朋友已经帮忙解决了,strcpy_s的问题以后再讨论。
    鉴于大家的热心,本贴再加100分,然后结贴。