none
ReleaseBuffer 有什么用呢? RRS feed

  • 问题

  • 程序代码:
    #include "u_def.h"
    #include <stdio.h>
    #include <afx.h>
    // #include "u_linearStruct.h"      
    
    
    int main( int ac, char **av )
    {
      char *pstr = NULL;
      CString strIn("zhong");
    
      pstr = strIn.GetBuffer(0);
      printf("0:%s\n", pstr);
    
      pstr = strIn.GetBuffer(1);
      printf("1:%s\n", pstr);
      
    
      strIn.ReleaseBuffer();
      printf("ReleaseBuffer:%s\n", pstr);
    
      strIn += "yunde";
      printf("+ :%s\n", pstr);
    
      strIn.ReleaseBuffer();
      printf("+ ReleaseBuffer:%s\n", pstr);
      
    
      return 0;
    }
    

    使用上面的代码发现,
    1)在CString变量的长度发生变化的时候,其内存地址均会被reallocated了,
    也就是ReleaseBuffer不管是否调用一次,pstr的地址都不会有效了,那为什么在MSDN上说
    使用了GetBuffer再执行其他的操作前需要嗲用ReleaseBuffer
    2)发现strIn.GetBuffer(0);和strIn.GetBuffer(1);得到相同的返回值,那这个参数有什么用呢 ?
    清钟沁桐
    2010年8月5日 14:48

答案

  • GetBuffer,ReleaseBuffer是用来做类似:strncpy(s.GetBuffer(1024),"xxxxx",1024);

    这样的事情的。因为很多c api需要char*作为输出。

    所以使用GetBuffer(X)能得到一个临时的最大长度为X的char*指针。

    ReleaseBuffer并不是释放内存,而是查找这个临时的buffer中\0的位置,以确定字符长的长度

    1.GetBuffer返回的指针是临时的,不是让你保存着一直使用的。

    2.当内部的buffer比较大,GetBuffer(0) GetBuffer(1)都可以使用这个buffer。

    • 已标记为答案 vfdff 2011年2月24日 18:05
    2011年1月9日 5:45

全部回复

  • 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 "

    麻烦把正确答案设为解答。
    2010年11月29日 9:56
    版主
  • 如何判定缓冲区是否被引用了呢?使用计数器?
    清钟沁桐
    2011年1月8日 16:58
  • GetBuffer,ReleaseBuffer是用来做类似:strncpy(s.GetBuffer(1024),"xxxxx",1024);

    这样的事情的。因为很多c api需要char*作为输出。

    所以使用GetBuffer(X)能得到一个临时的最大长度为X的char*指针。

    ReleaseBuffer并不是释放内存,而是查找这个临时的buffer中\0的位置,以确定字符长的长度

    1.GetBuffer返回的指针是临时的,不是让你保存着一直使用的。

    2.当内部的buffer比较大,GetBuffer(0) GetBuffer(1)都可以使用这个buffer。

    • 已标记为答案 vfdff 2011年2月24日 18:05
    2011年1月9日 5:45
  • Returns a pointer to the internal character buffer for the CString object. The returned LPTSTR is not const and thus allows direct modification of CString contents。

    CString::GetBuffer返回一个指向内部缓冲区的指针,你允许你修改该CString对象。

    CString strText(_T("Hello,World"));

    int len = strText.GetLength(); // 这里得到是长度是11

    如果你修改这里面的内容.

    TCHAR* pText = strText.GetBuffer(len);

    _tcscpy(pText, _T("ABC")); 

    上面你修改了pText指向的内容了,注意:但是这里你没用调用strText.ReleaseBuffer();

    AfxMessageBox(strText); // 可以看到strText的内容已经修改为"ABC"了。

    len = strText.GetLenth(); // 这里的长度仍然是11,而不是修改以后的3

    如果你修改以后,加上strText.RleaseBuffer();后面就正确了,MSDN里有这么一句话


    If you use the pointer returned by GetBuffer to change the string contents, you must call ReleaseBuffer before using any other CString member functions.

    2011年1月10日 3:26
    版主
  • CString strText(_T("Hello,World"));
     CString strMsg(_T(""));
     
     int len = strText.GetLength(); // 这里得到的长度是11 
     
     strMsg.Format(_T("1: %d"), len);
     AfxMessageBox(strMsg);
     
     //修改缓冲区的内容  
     TCHAR* pText = strText.GetBuffer(len);
     
     _tcscpy(pText, _T("ABC"));
     
     //strText.ReleaseBuffer(); // 注意这里,有和没有的区别,如果没有加这句的话AfxMessageBox(strText);显示的ABC,但是最后的AfxMessageBox(strMsg);显示还是11,
     AfxMessageBox(strText);

     strMsg.Format(_T("2: %d"), strText.GetLength());
     AfxMessageBox(strMsg);

    2011年1月10日 3:40
    版主