From: Joseph M. Newcomer on 19 Mar 2005 11:55 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 19 Mar 2005 12:09
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 |