Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Bug in CEdit::GetLine()??

272 views
Skip to first unread message

David Pochron

unread,
Aug 11, 2003, 1:14:56 AM8/11/03
to
I am trying to return a string from a single-line edit control using the
CEdit MFC class by following the sample code in the MSDN library. However,
it does not work properly when I try to use a CString buffer but works with a
stack-allocated buffer. Here are the 2 versions of the code. The first one
doesn't work, the second does:

// 'editbox' is declared as a CEdit variable via MFC wizard in the dialog
// class definition.

-A.-----------
int len;
CString buf;
LPTSTR ptr;

len = editbox.LineLength();
ptr = buf.GetBuffer(len);
editbox.GetLine(0, ptr, len);
buf.ReleaseBuffer(len);

-B.-----------
TCHAR buf[129];

editbox.GetLine(0, buf, 128);
buf[128] = 0;


When I trace the first version of the code which uses a CString buffer to get
the data, two things go wrong:

1) If the edit control is empty (no text) the editbox.GetLine(...) call
returns *two* null-terminators for the string in the buffer pointed to by
'ptr' instead of just 1. This causes a memory trashing error since
CString::GetBuffer() only allocates 1 byte for a single null-terminator for
the string. Not a big deal since the code can be changed to GetBuffer(len+1)
but annoying nonetheless.

2) The big problem is if the edit control only contains a single character as
the input text instead of putting that single character in the buffer (like
an "a" or a "4" or whatever) it puts an 01 00 in the buffer. Presumably,
this is the GetLine() doing it's "let's put the length of the returned string
as a word in the first 2 bytes of the buffer thing", but then why doesn't it
do that when 2 or more characters are input into the control? In such cases
it simply stores the returned string followed by a \0 to terminate the
string. (Which according to the docs it isn't supposed to do, either.)

What is stranger to me is why the second version of the code works (it still
stores a double \0 in the buffer when the control has an empty string) but
even with one character in the control, it properly returns just that
character as does input with 2 or more characters.

Despite the types being the same, I don't see why the first version does the
weird thing when one character is in the control vs. the second version which
always returns the string properly. Now, I know I can do the second version
of the code (or something like it with "buf = new TCHAR[len]") and have it
work, but I would really like to understand why it is broken with the CString
method of the first version which is what is given in the MSDN sample code.

The generated executable is using MFC70D.DLL version 7.0.9466.0 on Windows XP
Home.

----
David Pochron dp...@ticon.net


Jeff Partch

unread,
Aug 11, 2003, 9:29:52 AM8/11/03
to
[inline]

"David Pochron" <dp...@ticon.net> wrote in message
news:OEwc9e8X...@TK2MSFTNGP10.phx.gbl...

****
I don't find this to be true using the scheme I post below. Note that I
ReleaseBuffer based on the length returned by the call to GetLine.
****

>
> 2) The big problem is if the edit control only contains a single
character as
> the input text instead of putting that single character in the buffer
(like
> an "a" or a "4" or whatever) it puts an 01 00 in the buffer.
Presumably,
> this is the GetLine() doing it's "let's put the length of the returned
string
> as a word in the first 2 bytes of the buffer thing", but then why
doesn't it
> do that when 2 or more characters are input into the control? In such
cases
> it simply stores the returned string followed by a \0 to terminate the
> string. (Which according to the docs it isn't supposed to do, either.)

****
I think the EDIT is checking that buffer is at least sizeof(WORD) and
failing to read/write it in that case.
****


>
> What is stranger to me is why the second version of the code works (it
still
> stores a double \0 in the buffer when the control has an empty string)
but
> even with one character in the control, it properly returns just that
> character as does input with 2 or more characters.

****
In this case, your buffer is always > sizeof(WORD).
****


>
> Despite the types being the same, I don't see why the first version
does the
> weird thing when one character is in the control vs. the second
version which
> always returns the string properly. Now, I know I can do the second
version
> of the code (or something like it with "buf = new TCHAR[len]") and
have it
> work, but I would really like to understand why it is broken with the
CString
> method of the first version which is what is given in the MSDN sample
code.

****
Conclusion: I think what it is is that the buffer passed to GetLine
needs to be at least sizeof(WORD) in size, as the first WORD will
contain the size, and I think the EDIT control expects this too (through
whatever unstated validation scheme it uses). So something like...

int len;
CString buf;
LPTSTR ptr;

len = editbox.LineLength();
len = max(sizeof(WORD), len);
ptr = buf.GetBuffer(len);
len = editbox.GetLine(0, ptr, len);
buf.ReleaseBuffer(len);

...although, in reality I would probably forego the remainder if
LineLength returned 0. :)

--
Jeff Partch [VC++ MVP]


David Pochron

unread,
Aug 12, 2003, 1:27:08 AM8/12/03
to
"Jeff Partch" <je...@mvps.org> wrote in message
news:%23SVHnyA...@TK2MSFTNGP09.phx.gbl...

> Conclusion: I think what it is is that the buffer passed to GetLine
> needs to be at least sizeof(WORD) in size, as the first WORD will
> contain the size, and I think the EDIT control expects this too

Thanks! I was already always passing a minimum of 2 bytes of buffer to
GetLine since I was allocating len+1 in GetBuffer. The real trick was to
also pass that same size to the max size param in GetLine. That made it
happy and now it returns the string in all cases.


--
----
David Pochron dp...@ticon.net


0 new messages