From: Joseph M. Newcomer on
This is not a good practice; for example, read the CString::GetBuffer code. If the number
of outstanding refs to the string is > 1, you will always get a copy which will need to be
resynced. Since you cannot really decide whether or not there are other references without
making some dangerous assumptions, the failure to call ReleaseBuffer should always be
treated as an error.

joe

On Fri, 18 Mar 2005 11:19:34 -0800, "Tom Serface" <tserface(a)msn.com> wrote:

>Hi Craig,
>
>I think you only need to do this if you actually modify the string and need
>to resync it. So far as I know you don't have to do this if you pass the
>string as a const. That's why CString can do the automatic cast to LPCTSTR.
>However, that said, I don't think it hurts either so long as you don't
>change the length of the string...
>
>Tom
>
>"Craig S." <xxxx(a)ms.com> wrote in message
>news:u65B%2322KFHA.1280(a)TK2MSFTNGP09.phx.gbl...
>>A call to CString::GetBuffer() has to be followed by
>>CString::ReleaseBuffer() before you do anything else with the CString
>>object.
>>
>

Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Joseph M. Newcomer on
Many, many errors in the code below
On Thu, 17 Mar 2005 22:43:20 GMT, "jt" <jtsoft(a)hotmail.com> wrote:

>Being a newbie to MFC, I am having problems on copying CString to a char*
>
>Below is my attempt but I getting this error below:
>=====================================================
>Debug Assertion Failed!
>
>Program: C:\geac\GEACstatusptt.exe
>File: dbgheap.c
>Line: 1044
>
>Expression: _CrtIsValidHeapPointer(pUserData)
>
>Below is my code the way that I am doing now, look at switch 4 and
>this is where I call a DLL library "McaAddPageMember"
>======================================================
>char cPAGER_CODE[16];
****
TWO MAJOR MISTAKES IN ONE LINE!

Why "char"? If you ever need to write something like this, you should have used TCHAR.
Forget that 'char' exists as a data type; we are no longer programming PDP-11s. The very
few places you ever need to use 'char' will be obvious. but ALWAYS write Unicode-aware.

Allocating a fixed-size buffer like this is a fundamental programming error. Lose it
entirely. Use a CString:

CString cPAGER_CODE;
*****
>
>CPsnstatuspttApp::m_LogTrace.WriteLine("CPsnstatuspttView::Call_Page_Member(
>)");
>
>CTokenizer tok( cmdstr,",");
>CString cs;
>
//******
MAJOR ERROR: you do not initialize cPAGER_CODE before executing this code. Fortunately, by
using a CString, this error is eliminated
//*****
> id=0;
> while(tok.Next(cs))
> {
> switch (id){
>
> case 0: iPAGER_FORMAT = (WORD) _ttoi(cs); //Feature, paging format
> break;
> case 1: GEAC_PAGE_ID = cs;
> break;
> case 2: iRID = (WORD) _ttoi(cs); // rid
> break;
> case 3: iFREQ = (WORD)_ttoi(cs); //frequency
> break;
> case 4: wsprintf(cPAGER_CODE,"%s",cs.GetBuffer(cs.GetLength())); // pager
//****
SIX MAJOR ERRORS: you are calling wspritnf, which takes an LPCTSTR format, but you are
passing an 8-bit string format. It wants an LPTSTR buffer, but you are giving it an LPSTR.
And you are calling wsprintf, when you should be calling CString::Format. You are using
GetBuffer when it is not needed, and you are failing to call ReleaseBuffer. And to make it
all pointless, you are doing this for the purpose of copying a string! If we let
cPAGER_CODE be the CString it should be, then you only need to write

cPAGER_CODE = cs;
is a lot simpler, faster, and will not crash you with some disastrous error if cs happens
to be > 15 characters, and will work in Unicode.

Read my essay on CStrings on my MVP Tips site.
//*****
>code
> bNumDigits=cs.GetLength();
> break;
> }
> id++;
> }
>
> pEntry = NULL;
>
> pos = g_RCtable.GetHeadPosition();
> while (pos)
> {
> _rid *pCurrent = g_RCtable.GetNext(pos);
> if (pCurrent->RC_id == iRID){
>
> if (iFREQ==0)
> iFREQ=NULL_FREQ;
>
> CPsnstatuspttApp::m_LogTrace.WriteLine("McaAddPageMember PAGER
>CODE:%s",cPAGER_CODE);
//****
I presume WriteLine is some method of your code that takes a formatting string (which
should be in _T()) and formats the line.
//****
>
> if(McaAddPageMember(pCurrent->LC_id, iFREQ, iPAGER_FORMAT, bNumDigits,
>cPAGER_CODE ) )
//****
use (LPCTSTR)cPAGER_CODE unless the argument is already LPCTSTR, in which case nothing
special is required
//*****
> {
> CPsnstatuspttApp::m_LogTrace.WriteLine(" SUCCESSFUL API Call
>McaAddPageMember");
>
> if ( McaBeginPaging () )
> {
> CPsnstatuspttApp::m_LogTrace.WriteLine("SUCCESSFUL API Call
>McaBeginPaging");
> sock.Send(msg.GetBuffer(msg.GetLength()), msg.GetLength());
//****
Why do you assume that sock.Send (presuming this is some sort of TCP/IP or UDP network
socket) actually worked? If you are using CSocket, you are doomed anyway, and for
CAsyncSocket you must test the result.
//****
> }
> else
> {
> CPsnstatuspttApp::m_LogTrace.WriteLine(" FAILED API Call
>McaBeginPaging");
> sock.Send(msg.GetBuffer(msg.GetLength()), msg.GetLength());
//****
sock.Send((LPCTSTR)msg, msg.GetLength() * sizeof(TCHAR));
No GetBuffer required. And I see no ReleaseBuffer here
//****
> }
>
> }
> else
> {
> RetMsg="FAILED API Call McaAddPageMember()";
> CPsnstatuspttApp::m_LogTrace.WriteLine(RetMsg);
> sock.Send(msg.GetBuffer(msg.GetLength()), msg.GetLength());
//****
sock.Send((LPCTSTR)msg, msg.GetLength() * sizeof(TCHAR));
No GetBuffer required. And thus the missing ReleaseBuffer is irrelevant
//****
> }
> break;
> }
> pEntry = pCurrent;
> }
>

Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm