17

From CString to char*, ReleaseBuffer() must be used after GetBuffer(). But why? What will happen if I don't use ReleaseBuffer() after GetBuffer()?

Can somebody show me an example? Thanks.

Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164
Landy
  • 379
  • 1
  • 4
  • 10

4 Answers4

11

I'm not sure that this will cause a memory leak, but you must call ReleaseBuffer to ensure that the private members of CString are updated. For example, ReleaseBuffer will update the length field of the CString by looking for the terminating null character.

Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164
Nick Meyer
  • 39,212
  • 14
  • 67
  • 75
  • 1
    @Nick, thank you. I just wrote a small program to test ReleaseBuffer(), you are right!! Thank you! – Landy Feb 26 '10 at 16:21
  • According to Microsoft documentation: "If you use the pointer returned by GetBuffer to change the string contents, you must call ReleaseBuffer before using any other CString member functions.". I.e. you don't always need to use 'em in pairs. – SamWhan Apr 12 '18 at 15:05
  • @SamWhan if you don't intend to change the string contents you should use a `const` pointer instead, which doesn't require `GetBuffer` - just a cast to `PCTSTR`. – Mark Ransom Feb 28 '19 at 20:45
3

What will happen if I don't use ReleaseBuffer() after GetBuffer()?

I haven't used MFC (and hopefully won't ever have to touch it with a ten-foot pole) but, as a rule of thumb, whenever you have an API that has both GetXXX() and ReleaseXXX() (especially when the result of GetXXX() conveniently is of the type that ReleaseXXX() takes) -- then when you forget to call ReleaseXXX() for every one of your GetXXX() calls, you will leak an XXX.

Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164
sbi
  • 219,715
  • 46
  • 258
  • 445
  • @sbi, thank you. From this post - http://stackoverflow.com/questions/559483/cstring-to-char, "calling the GetBuffer method won't lead to any memory leaks. Because the destructor is going to deallocate the buffer anyway. " – Landy Feb 26 '10 at 15:59
  • @Landy: Well, there you go. So, in this case, the rule of thumb seems to fail. I guess that's why it is called a "rule of thumb", after all, no? Well, did I say I dislike MFC? Now there's one more reason to do so. An API where `GetXXX()` and `ReleaseXXX()` don't come in pairs just plain sucks... Anyway, from http://msdn.microsoft.com/en-us/library/awkwbzyc.aspx: "After you modify the contents of a CString object directly, you must call ReleaseBuffer before you call any other CString member functions." – sbi Feb 26 '10 at 16:16
  • Thank you. MSDN says "After you modify the contents of a CString object directly, you must call ReleaseBuffer before you call any other CString member functions." But MSDN doesn't say why I *must* call ReleaseBuffer. In Nick's post, he said ReleaseBuffer() will update the length field of CString. It's a good reason I think. Thank you. – Landy Feb 26 '10 at 16:31
  • 1
    CString source code is available in atlsimplestr.h. Debugging through it, I see that CSring::ReleaseBuffre() only sets the length of the string, and doesn't do memory deallocation, allocation, or reallocation. nDataLength of CStringData (used internally by CString) holds string length. nAllocLength holds the buffer length. BufferRelase only changes nDataLength. Doesn't even touch nAllocLength . I feel this is a case of ambiguity in function name combined with terrible documentation, which MS is good at, fortunately we have the source code (unfortunately which MS can change any time). – Sahil Singh Dec 23 '18 at 05:33
0

If you do not modify the contents of the CString using the pointer obtained using GetBuffer(), you do NOT need to call ReleaseBuffer() afterwards

0

Here's an example of how I used CString::GetBuffer() and CString::ReleaseBuffer() :

LPTSTR pUnitBuffer = pAPBElement->m_strUnits.GetBuffer(APB_UNIT_SIZE);
if (pUnitBuffer != "")
{
   if (strncmp(pAPBElement->m_strUnits, (char*)pszBuffer[nLoop - nFirst], APB_UNIT_SIZE) != 0)
   {    
     LPTSTR pUnitOriginal = pAPBElement->m_strOriginal.GetBuffer(APB_UNIT_SIZE);

     strncpy(pUnitBuffer, 
            (char*)&pszBuffer[nLoop - nFirst], 
            APB_UNIT_SIZE);

     strncpy(pUnitOriginal, 
            (char*)&pszBuffer[nLoop - nFirst], 
            APB_UNIT_SIZE);

     pAPBElement->m_strOriginal.ReleaseBuffer();
    }
}
pAPBElement->m_strUnits.ReleaseBuffer();
Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164
Jim Lahman
  • 2,691
  • 2
  • 25
  • 21