我编写了一个Dll,函数参数为CString&,在Dll中我改变了该CString值。
现在我调用该函数,传入一个 CString strText = ""进入该函数,结果出错。检查发现,当我把strText 赋值为3个获3个以下的汉字时没问题,但赋值到4个汉字时就会出现错误。请问是否要手动为他分配空间才行吗?
现在我调用该函数,传入一个 CString strText = ""进入该函数,结果出错。检查发现,当我把strText 赋值为3个获3个以下的汉字时没问题,但赋值到4个汉字时就会出现错误。请问是否要手动为他分配空间才行吗?
::GetWindowText(m_hWnd, rString.GetBufferSetLength(nLen), nLen+1);
//返回rString的internal character buffer ,
//若有必要,减少或增加buffer的长度以匹配nLen字节。
rString.ReleaseBuffer();
//对CString对象,调用了GetBuffer后最好调用ReleaseBuffer()
//已避免对进行其他操作时出错。如果是在dll中这样使用的话,如果需要分配空间,该空间似乎应该由dll分配,但是该CString的引用传回去后又是由exe使用(并销毁),这样也许要出问题吧?关注。
1、CString()构造临时CString对象
2、operator= 重载的赋值运算看看到底错误出在哪里?有个概念要搞清楚,加载的DLL其实就是当前进程的一部分
系统只是将DLL中映射到进程地址中DLL分配或者EXE分配的内存是一样的你可以将代码贴出来,研究一下
在 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= "同志们好阿";时比传入时候的长度大。真迷惑。
用char*吧,其长度可再用一函数取得。
用char*吧,其长度可再用一函数取得。
-----------------------------------------------
有啊,你看看GetWindowText,不是API,是CWnd的一个类成员函数,是传入CString&引用的,同我这个一样。
哈,帮你顶!
CString用起来很方便,而且大多数程序都是不需要跨平台的,那就没有理由不用CString。遇到问题就绕过去并不总是好的。char*是可以用,谁都知道,但是我们就是要开发一个方便使用的,用CString引用做接口的引出函数,这不比chaf*接口的用起来方便吗?引用方式调用CString的问题,我也遇到了,是在动态库调用动态库的时候遇到的,我也是绕过去了,不过一直记挂着。我怀疑是函数的引出方式问题,就是dllimport dllexport __stdcall之类的这些东西没用好。
char*太麻烦了,况且我很多函数需要用到类似的参数接口。难道就无法解决这个问题吗?
为什么MFC中的CWnd::GetWindowText可以用CString&呢?
按理说动态库应该是没有自己的堆的啊,是mfc做的手脚吗?
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中的原代码。
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;
我试了一下,动态库里面的_crtheap是0x00880000,到了外面,_crtheap是0x00910000,因此在我的那个例子里,动态库和应用程序的堆肯定是不一样的。解决办法出台:msdn说,动态连接mfc的扩展dll可以解决诸如此类的问题。尝试中,你们也可以试试。
证实了,扩展dll没有任何上述这些问题。无论是动态库里面分配内存外面删,还是引用方式调用CString,都OK。因此,涉及MFC的动态库,最好都写成扩展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了。
什么意思?删除了xxx.h文件,那不用其他文件来替代吗?
怎么样设置这个开关?谢谢