我编写了一个Dll,函数参数为CString&,在Dll中我改变了该CString值。
现在我调用该函数,传入一个 CString strText = ""进入该函数,结果出错。检查发现,当我把strText 赋值为3个获3个以下的汉字时没问题,但赋值到4个汉字时就会出现错误。请问是否要手动为他分配空间才行吗?

解决方案 »

  1.   

    GetWindowText:
             ::GetWindowText(m_hWnd, rString.GetBufferSetLength(nLen), nLen+1);
                           //返回rString的internal character buffer ,
                           //若有必要,减少或增加buffer的长度以匹配nLen字节。
    rString.ReleaseBuffer();
                           //对CString对象,调用了GetBuffer后最好调用ReleaseBuffer()
                           //已避免对进行其他操作时出错。如果是在dll中这样使用的话,如果需要分配空间,该空间似乎应该由dll分配,但是该CString的引用传回去后又是由exe使用(并销毁),这样也许要出问题吧?关注。
      

  2.   

    F11 单步调试一下strText = "同志们好";这里会执行两个函数
    1、CString()构造临时CString对象
    2、operator= 重载的赋值运算看看到底错误出在哪里?有个概念要搞清楚,加载的DLL其实就是当前进程的一部分
    系统只是将DLL中映射到进程地址中DLL分配或者EXE分配的内存是一样的你可以将代码贴出来,研究一下
      

  3.   

    我的代码很简单
    在 dll中:void GetTestText(CString& strText)
    {
    static BOOL flag = true;
    if(flag)
    strText= "你好";//两个汉字
    else
    strText= "同志们好阿";//5个汉字
    flag = !flag;
    }
    在调用程序中:void CDllClientDlg::OnButton2() 
    {
    // TODO: Add your control notification handler code here
    CString strText = "";
    strText = "你好";//初始化为有两个汉字
    GetTestText(strText);
    AfxMessageBox(strText);
    }
    调用结果就是第一次成功,第二次就不行了。 因为第二次执行到strText= "同志们好阿";时比传入时候的长度大。真迷惑。
      

  4.   

    干嘛要用CString,Windows API有这样的参数吗?
    用char*吧,其长度可再用一函数取得。
      

  5.   

    干嘛要用CString,Windows API有这样的参数吗?
    用char*吧,其长度可再用一函数取得。
    -----------------------------------------------
    有啊,你看看GetWindowText,不是API,是CWnd的一个类成员函数,是传入CString&引用的,同我这个一样。
      

  6.   

    完全是两回事了。非VC可没有CString这个类了,那么你的DLL实用吗?
    哈,帮你顶!
      

  7.   

    可能会出错,因为cstring里面有创建malloc,free内存操作,你在EXE里面的时候malloc,free用的是EXE的C库stack,而在DLL又是用的DLL的C库STACK,这样显然会出错。
      

  8.   


    CString用起来很方便,而且大多数程序都是不需要跨平台的,那就没有理由不用CString。遇到问题就绕过去并不总是好的。char*是可以用,谁都知道,但是我们就是要开发一个方便使用的,用CString引用做接口的引出函数,这不比chaf*接口的用起来方便吗?引用方式调用CString的问题,我也遇到了,是在动态库调用动态库的时候遇到的,我也是绕过去了,不过一直记挂着。我怀疑是函数的引出方式问题,就是dllimport dllexport __stdcall之类的这些东西没用好。
      

  9.   

    sevencat(七猫) 说的好像是对的,我在动态库里面new内存,外面来delete,会报错。
      

  10.   

    调用者也是MFC程序,为什么不能用CString?
    char*太麻烦了,况且我很多函数需要用到类似的参数接口。难道就无法解决这个问题吗?
    为什么MFC中的CWnd::GetWindowText可以用CString&呢?
      

  11.   

    他们在不同的内存堆上分配销毁,所以会出错。你可以试着MFC和C库全部链接到动态库里面试试,我估计应该没问题了。
      

  12.   


    按理说动态库应该是没有自己的堆的啊,是mfc做的手脚吗?
      

  13.   

    free的代码如下:
    void __cdecl _free_base (void * pBlock)
    {
            if (pBlock == NULL)
                return;        RTCCALLBACK(_RTC_Free_hook, (pBlock, 0));#ifndef _WIN64
            if ( __active_heap == __V6_HEAP )
            {
                PHEADER     pHeader;#ifdef _MT
                _mlock( _HEAP_LOCK );
                __try {
    #endif  /* _MT */            if ((pHeader = __sbh_find_block(pBlock)) != NULL)
                    __sbh_free_block(pHeader, pBlock);#ifdef _MT
                }
                __finally {
                    _munlock( _HEAP_LOCK );
                }
    #endif  /* _MT */            if (pHeader == NULL)
                    HeapFree(_crtheap, 0, pBlock);
            }
    #ifdef CRTDLL
            else if ( __active_heap == __V5_HEAP )
            {
                __old_sbh_region_t *preg;
                __old_sbh_page_t *  ppage;
                __old_page_map_t *  pmap;
    #ifdef _MT
                _mlock(_HEAP_LOCK );
                __try {
    #endif  /* _MT */            if ( (pmap = __old_sbh_find_block(pBlock, &preg, &ppage)) != NULL )
                    __old_sbh_free_block(preg, ppage, pmap);#ifdef _MT
                }
                __finally {
                    _munlock(_HEAP_LOCK );
                }
    #endif  /* _MT */            if (pmap == NULL)
                    HeapFree(_crtheap, 0, pBlock);
            }
    #endif  /* CRTDLL */
            else    //  __active_heap == __SYSTEM_HEAP
    #endif  /* _WIN64 */
            {
                HeapFree(_crtheap, 0, pBlock);
            }
    }
    里面调用了一个块查找的部分
    PHEADER __cdecl __sbh_find_block (void * pvAlloc)
    {
            PHEADER         pHeaderLast = __sbh_pHeaderList + __sbh_cntHeaderList;
            PHEADER         pHeader;
            unsigned int    offRegion;        //  scan through the header list to determine if entry
            //  is in the region heap data reserved address space
            pHeader = __sbh_pHeaderList;
            while (pHeader < pHeaderLast)
            {
                offRegion = (unsigned int)((uintptr_t)pvAlloc - (uintptr_t)pHeader->pHeapData);
                if (offRegion < BYTES_PER_REGION)
                    return pHeader;
                pHeader++;
            }
            return NULL;
    }
    MFC的operator new里面也是调用的这个,可查看afxmem.cpp中的原代码。
      

  14.   

    这些是一些C内存堆全局的变量(小内存块,大的还要WIN去分配)
    size_t      __sbh_threshold;
    int         __sbh_initialized;PHEADER     __sbh_pHeaderList;          //  pointer to list start
    PHEADER     __sbh_pHeaderScan;          //  pointer to list rover
    int         __sbh_sizeHeaderList;       //  allocated size of list
    int         __sbh_cntHeaderList;        //  count of entries definedPHEADER     __sbh_pHeaderDefer;
    int         __sbh_indGroupDefer;
      

  15.   


    我试了一下,动态库里面的_crtheap是0x00880000,到了外面,_crtheap是0x00910000,因此在我的那个例子里,动态库和应用程序的堆肯定是不一样的。解决办法出台:msdn说,动态连接mfc的扩展dll可以解决诸如此类的问题。尝试中,你们也可以试试。
      

  16.   


    证实了,扩展dll没有任何上述这些问题。无论是动态库里面分配内存外面删,还是引用方式调用CString,都OK。因此,涉及MFC的动态库,最好都写成扩展dll。反正至少到目前为止,我知道扩展动态库是没有上述这些问题的。
      

  17.   

    简易的将普通dll改成扩展dll的办法:
    1、删除xxx.h,就是包含CYouDllApp的那个头文件。
    2、随便找一个扩展dll比如yyy.dll,将它的yyy.cpp拷贝到xxx.cpp,不用担心,直接可以用。
    3、修改project->setting,将c/c++中的_USRDLL改为_AFXEXT,并且使用MT和DMT。OK,一个普通dll已经变成扩展的dll了。
      

  18.   

    2、随便找一个扩展dll比如yyy.dll,将它的yyy.cpp拷贝到xxx.cpp,不用担心,直接可以用。------------------------------------------------------------
    什么意思?删除了xxx.h文件,那不用其他文件来替代吗?
      

  19.   

    你可以试着MFC和C库全部链接到动态库里面试试,我估计应该没问题了。----------------------------------------------------------------
    怎么样设置这个开关?谢谢
      

  20.   

    faint,看来我没说清楚转换成扩展的办法。你自己建一个扩展的动态库,比较一下和普通的动态库有什么不同吧。