看了一下源代码,只是将CStringData::nDataLength改为内存块中字符的实际长度,
不该也没有什么问题呀?以下是msdn的CString::ReleaseBuffer中的例子CString s;
s = "abc";
LPTSTR p = s.GetBuffer( 1024 );
strcpy(p, "abc");   // use the buffer directly
ASSERT( s.GetLength() == 3 ); // String length = 3
s.ReleaseBuffer();  // Surplus memory released, p is now invalid.
ASSERT( s.GetLength() == 3 ); // Length still 3在调用了s.ReleaseBuffer();后,msdn说p is invalid,但是还是可以在用
strcpy(p,"rickey");
AfxMessage(p);
没有什么问题呀???

解决方案 »

  1.   

    首先,告诉你ReleaseBuffer的用处:
      如果你想要使你的CString对象的缓冲区直接指向别人,那么CString对象内部的缓冲区指针谁来释放?当然是你!办法就是调用ReleaseBuffer。其次,内存invalid并不代表不能用。如果有这样的代码:
      int *p = new int;//假设p==0xffff2222
      delete p;//p is invalid
               //但是此时p==0xffff2222
      在这之后,如果你再使用p就不一定安全了。也可能有这种情况:
      在delete p之后,使用p之前,恰好操作系统中的任何线程都没有使用地址0xffff2222,那么这是你的代码也不会除错,只是其内容是一些随机值。
      所以,你应该保持这样的风格:
      在delete一个指针之后把他赋值为0。
      而0x00000000永远是不能读的,所以保证出错,及早解决问题。
      

  2.   


    CString::CString()
    {
    Init();
    }
    _AFX_INLINE void CString::Init()
    { m_pchData = afxEmptyString.m_pchData; }重新分配一块内存,把原来的数据拷贝过去,释放原来的内存.
    LPTSTR CString::GetBuffer(int nMinBufLength)
    {
    ....
    // we have to grow the buffer
    CStringData* pOldData = GetData();
    int nOldLen = GetData()->nDataLength;   // AllocBuffer will tromp it
    if (nMinBufLength < nOldLen)
    nMinBufLength = nOldLen;
    AllocBuffer(nMinBufLength);
    memcpy(m_pchData, pOldData->data(), (nOldLen+1)*sizeof(TCHAR));
    GetData()->nDataLength = nOldLen;
    String::Release(pOldData);
    ....
    }如果缓冲区没有被引用,则直接将要设置长度的最后一位置零.
    void CString::ReleaseBuffer(int nNewLength)
    {
    CopyBeforeWrite();  // just in case GetBuffer was not called if (nNewLength == -1)
    nNewLength = lstrlen(m_pchData); // zero terminated ASSERT(nNewLength <= GetData()->nAllocLength);
    GetData()->nDataLength = nNewLength;
    m_pchData[nNewLength] = '\0';
    }GetBuffer和ReleaseBuffer函数是为了解决使用strcpy时字符串会超过缓冲区大小的情况. LPCTSTR 重载操作符获得的字符串指针不能作为左值修改其中数据,因为这有可能引起指针越界或使该指针无效.所以要使用Getbuffer和ReleaseBuffer如下:
    CString str;
    str = "abcdef";
            //strcpy(LPCTSTR(str), "1234567890");是行不通的.
    LPTSTR pStr = str.GetBuffer(16); //如果不重新分配的话,可能造成                                         //指针越界
    lstrcpy(pStr, "1234567890");
    str.ReleaseBuffer(5);   //释放缓冲到指定的字符串长度
            现在的字符串是"12345"