Re: Reentrancy issue
"Joseph M. Newcomer" <newcomer@flounder.com> wrote in message
news:4s0hp3tp6fa7m8odpv20c5getaihapmev4@4ax.com...
[I missed the start of this thread, just commenting on what's below]
Actually, it looks like he's returning a reference to a member variable -
that's ok. The Format call is _definitely_ wrong. A "%s" in Format()
CANNOT take a CString. You must use the operator LPCTSTR() method on
CString (cast CString to an LPCTSTR)
****
Absolutely not true. It works just fine, and has since the first design
of MFC. I have
on the order of 750K lines of product code out there, not one line of
which has an LPCTSTR
cast on a CString in a Format statement.
****
Then you've been writing code with errors that have been masked by a CString
implementation detail. Calling Format() e.g.:
CString strMsg;
CString strContents = _T("Hello world");
strMsg.Format ("%s is the contents of the string", strContents);
is incorrect. You should instead specify:
strMsg.Format ("%s is the contents of the string", (LPCTSTR)
strContents);
because the compiler does not automatically call CString::operator LPCTSTR()
as it does not know that Format() requires an LPCTSTR, due to that being
specified in the format string, which the compiler does not know about.
The reason your erroneous code works: because CString has no virtual
functions, it has no v-table, and thus the address of strContents is the
same as the first data member, which is the LPTSTR buffer. So
&strContents == &strContents.buffer // <-- whatever the "buffer" is
called, I don't know
But if Microsoft or someone else revised CString to have a v-table, you'd be
really sunk. I doubt anyone is interested in formatting the address of the
v-table! ;)
However, that said, since the OP is re-using the same variable for each
call, it's unlikely he'll get what he wants. It's going to depend on
order of evaluation.
****
It just doesn't make sense to return a CString& from this kind of
function. I missed that
it was a member variable, but it is still a poor design. Perhaps it is
some delusional
system that thinks that returning a CString is "poor performance" but note
that LoadString
is going to be the biggest cost; by comparison, the cost of returning a
copy of the
CString is so tiny as to not even matter. But in C, this might have been
considered "good
style" in the days before we understood that it was, as style, abysmal
because it was
non-reentrant.
"Non-reentrant" is not the right term. The function runs to completion
without being re-entered. The problem is the value it returns is not cached
before it is overwritten by another call. I don't know a term for this, but
I don't think "re-entrancy" is it.
Clever programmers who think they are optimizing code by writing bad code
are one of the
greatest sources of bugs we have.
If these programmers are guilty of anything, it's of not changing their
practice with the times. They weren't born with a desire to optimize, it
was a highly valued skill 20 years ago when you were seen as a weak
programmer writing:
// Iterate each character in a string
LPCTSTR pBuf = "Something to iterate";
int len = strlen(pBuf);
for (int i=0; i < len; i++)
DoSomething(pBuf[i]);
instead of:
// Iterate each character in a string really fast
LPCTSTR pBuf = "Something to iterate";
for (LPCTSTR p = pBuf; *p; )
DoSomething(*p++);
So to ignore history and come down on these programmers who do such things
is not really giving them their due for having learned a good craft way back
when. I agree they need to update their thinking, however.
Note that another way to tell a real naive programmer is that they write
code like
if(bRet == FALSE)
which is pointless, redundant, and error-prone. They don't seem to
understand the concept
of "BOOL" which is ALREADY a true-or-false value, and feel a compulsion to
write poor code
like this. I consider this as poor as writing
if( (a > 0) == FALSE)
Precisely what part of "boolean value" is incomprehensible and demands
being compared to
another boolean value to obtain a boolean value equal to the original
boolean value, or
the complement of the original boolean value?
****
You also need to recognize history here... I think it was old BASIC that had
no boolean type, so you wrote code like:
dim i as integer;
i = 1;
if ( i = 1 ) then
DoSomething
Same thing goes here as before: give programmers their due for learning a
craft, but encourage them to update their thinking. Don't write them off as
"naive programmers" worthy of no respect.
-- David