我现在在维护一个比较大的工程,其中有多个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");程序又可以正常运行.但好像系统又极不稳定.请赐教....

解决方案 »

  1.   

    //strcore.cpp#include "stdafx.h"
    #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; }....
    ....
      

  2.   

    There is sure some bug in CString, I also have such experience.
    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.
      

  3.   


    为什么在DLL中得到的_afxPchNil与在调用它的EXE文件取得的不一样.
    关于它的声明,我上面已贴出
      

  4.   

    对了,你这段代码是正确的,至少它在现在的VC版本中是可以的.只要你在中间不对a进行LockBuffer(...)CString a="aaa";
    CString b="adfsf";
    ...
    a = a + "ddd";
    a = "a string longer than its original"; //then it may fail at here.
      

  5.   

    no, my code is just simular to that. Only assign new string value to it, it seems that if I declare several CString variable, then only the first few works well, but some others fail. the string assigned to it is not long string, less than 100 chars!
    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.
      

  6.   

    DLL中得到的_afxPchNil与在调用它的EXE文件不一样可能是他们使用了不同的run-time library,又或者是因为使用了不同的预定义宏,导致CString类在dll和exe中的结构并不一样。
    我觉得DLL接口函数中最好只使用简单类型。不要用CString,用LPTSTR代替!
      

  7.   

    对于有些由于内存引发的异常,我们可以捕获它并设法挽回它.但现在的问题是,我已确切地知道错误的地方,可我却没办法知道它为什么会这样?实际上是这样的:
    CString a;
    a = "test"; //假如它在同一EXE模块中,现在没问题.但是,这样即不行,而且原来的代码没问题
    CString a;
    DllTest(a);__declspec (dllexport) int PASCAL EXPORT DllTest(CString& strRet)//接口函数
    {
     strRet = "test";
    }我分析,肯定是那块地方对它产生了影响.
      

  8.   

    to: comet(二子乘舟) 
    我传的是引用,即指针(换说没关系),除非你完全抛弃CString,否则你转换为LPTSTR也一样有问题.
      

  9.   

    #define extern __declspec( selectany ) AFX_STATIC_DATAAFX_STATIC_DATA int _afxInitData[] = { -1, 0, 0, 0 };
    AFX_STATIC_DATA CStringData* _afxDataNil = (CStringData*)&_afxInitData;在msdn上说,加了这样的__declspec(selectany)修饰符,在DLL及EXE中只会初始化一次,而且是全局外连的,
    但现在两个地方的地址不一样.谁知道,再加200分(讨论者也可加分).
      

  10.   

    换为LPTSTR不会有问题的.
    你可以看看其实所有的需要传递字符串的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,.....);
    }
    就不会有问题的了。
      

  11.   

    http://www.cuj.com/experts/1906/alexandr.htm
    you may get some idea about the trouble with COW strings
      

  12.   

    哈哈...
    原因终于找到了,不过现在没时间详细解释,我打算这几天对CString做一个全面的总结,以把自己的经验供大家供考.各位有何意见,讨论者都有分.
    有精辟分析者更是高分相送.
      

  13.   

    非常不好意思,昨天下午有事,提前下班了,所以没结贴.
    今天写一篇关于CString的总结,也对该问题进行了分析解答.
    请浏览:
    http://www.csdn.net/expert/topic/749/749795.xml?temp=.168667
    http://www.csdn.net/expert/topic/749/749810.xml?temp=.4293024
      

  14.   

    是不是在test(int a, CString& strRet /*出参*/)内部使用了new char[xxx],然后用strcpy或strncpy、memcpy等函数赋值给CString类的?这种问题我也遇到过的!