我现在在维护一个比较大的工程,其中有多个DLL,由于需要,稍微加了一些功能(10行代码),
导致程序出现了一个莫名其名的问题,即Debug正常,而Release不行,退出.
这几天我一直在调试这个bug,终于找出是由于CString引起的. 后来我没办法,把整个CString
实现代码全部过一遍,查看其究竟到底是怎样实现的.
功夫不负有心人,现在取得了比较大的进展,其原因就是:
我其中有一个DLL接口函数类似这样的定义的: __declspec (dllexport) int PASCAL EXPORT test(int a, CString& strRet /*出参*/);
当调用这个函数后, 它需要赋值返回strRet = "abc";这样,在其内部,重新进行内存分配(报错),
其原因就是DLL内部的_afxPchNil的值与实际strRet的&_afxInitData值不一致,导致释放本没有分配的内存.我想问,为什么外部的_afxPchNil与DLL里面的_afxPchNil的值不一样.而且特奇怪,只要我在程序任何地方,
加上这样一句CString("A");程序又可以正常运行.但好像系统又极不稳定.请赐教....
导致程序出现了一个莫名其名的问题,即Debug正常,而Release不行,退出.
这几天我一直在调试这个bug,终于找出是由于CString引起的. 后来我没办法,把整个CString
实现代码全部过一遍,查看其究竟到底是怎样实现的.
功夫不负有心人,现在取得了比较大的进展,其原因就是:
我其中有一个DLL接口函数类似这样的定义的: __declspec (dllexport) int PASCAL EXPORT test(int a, CString& strRet /*出参*/);
当调用这个函数后, 它需要赋值返回strRet = "abc";这样,在其内部,重新进行内存分配(报错),
其原因就是DLL内部的_afxPchNil的值与实际strRet的&_afxInitData值不一致,导致释放本没有分配的内存.我想问,为什么外部的_afxPchNil与DLL里面的_afxPchNil的值不一样.而且特奇怪,只要我在程序任何地方,
加上这样一句CString("A");程序又可以正常运行.但好像系统又极不稳定.请赐教....
#include "fixalloc.h"#ifdef AFX_CORE1_SEG
#pragma code_seg(AFX_CORE1_SEG)
#endif#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif#define new DEBUG_NEW/////////////////////////////////////////////////////////////////////////////
// static class data, special inlines// afxChNil is left for backward compatibility
AFX_DATADEF TCHAR afxChNil = '\0';// For an empty string, m_pchData will point here
// (note: avoids special case of checking for NULL m_pchData)
// empty string data (and locked)
AFX_STATIC_DATA int _afxInitData[] = { -1, 0, 0, 0 };
AFX_STATIC_DATA CStringData* _afxDataNil = (CStringData*)&_afxInitData;
AFX_COMDAT LPCTSTR _afxPchNil = (LPCTSTR)(((BYTE*)&_afxInitData)+sizeof(CStringData));
// special function to make afxEmptyString work even during initialization
const CString& AFXAPI AfxGetEmptyString()
{ return *(CString*)&_afxPchNil; }....
....
eg.
CString a="aaa";
CString b="adfsf";
...
a = a + "ddd";
a = "a string longer than its original"; //then it may fail at here.
So I sugest you avoiding it.
为什么在DLL中得到的_afxPchNil与在调用它的EXE文件取得的不一样.
关于它的声明,我上面已贴出
CString b="adfsf";
...
a = a + "ddd";
a = "a string longer than its original"; //then it may fail at here.
I don't know what is wrong with my code or your code, sorry. In fact I also see some one else complained on CString before in csdn, vc page.
我觉得DLL接口函数中最好只使用简单类型。不要用CString,用LPTSTR代替!
CString a;
a = "test"; //假如它在同一EXE模块中,现在没问题.但是,这样即不行,而且原来的代码没问题
CString a;
DllTest(a);__declspec (dllexport) int PASCAL EXPORT DllTest(CString& strRet)//接口函数
{
strRet = "test";
}我分析,肯定是那块地方对它产生了影响.
我传的是引用,即指针(换说没关系),除非你完全抛弃CString,否则你转换为LPTSTR也一样有问题.
AFX_STATIC_DATA CStringData* _afxDataNil = (CStringData*)&_afxInitData;在msdn上说,加了这样的__declspec(selectany)修饰符,在DLL及EXE中只会初始化一次,而且是全局外连的,
但现在两个地方的地址不一样.谁知道,再加200分(讨论者也可加分).
你可以看看其实所有的需要传递字符串的API函数都是这种形式。
DWORD GetModuleFileName(
HMODULE hModule, // handle to module to find filename for
LPTSTR lpFilename, // pointer to buffer to receive module path
DWORD nSize // size of buffer, in characters
);你的dll函数改为
__declspec (dllexport) int WINAPI DllTest(LPTSTR strRet,DWORD nSize)
{
......
strcpy(strRet,.....);
}
就不会有问题的了。
you may get some idea about the trouble with COW strings
原因终于找到了,不过现在没时间详细解释,我打算这几天对CString做一个全面的总结,以把自己的经验供大家供考.各位有何意见,讨论者都有分.
有精辟分析者更是高分相送.
今天写一篇关于CString的总结,也对该问题进行了分析解答.
请浏览:
http://www.csdn.net/expert/topic/749/749795.xml?temp=.168667
http://www.csdn.net/expert/topic/749/749810.xml?temp=.4293024