Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2003-07

Lazarus ansistring AV?

6 messages · 4 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Micha Nelissen

Hi,

Currently, lazarus crashes continually on my box. Backtrace:

#0 $006b2ed9 in SYSWIN32$$_ANSISTR_DECR_REF$POINTER () #1 $006b2f88 in SYSWIN32$$_ANSISTR_ASSIGN$POINTER$POINTER () #2 $0067a278 in WINDOWPROC (WINDOW=5964548, MSG=330, WPARAM=0, LPARAM=50054128)
at win32callback.inc:148
#3 $77e12ca8 in _size_of_stack_reserve__ ()
#4 $77e14764 in _size_of_stack_reserve__ ()
#5 $77e273a2 in _size_of_stack_reserve__ ()
#6 $77fa15ef in ?? ()
#7 $77e153a1 in _size_of_stack_reserve__ ()
#8 $0068302b in TWIN32OBJECT__SENDMESSAGE (HANDLEWND=5964548, MSG=330, WPARAM=0, LPARAM=50054128,
this=$876dd0) at win32winapi.inc:1940
#9 $00662ef5 in SENDMESSAGE (HANDLEWND=5964548, MSG=330, WPARAM=0, LPARAM=50054128)
at winapi.inc:950

Is this a bug in the ansistring functions? Sometimes it starts bugging me, then mysteriously disappears again. But now it doesn't disappear :(. Any hints, please?

Thanks,

Micha.

Reply by email

Marc Weustink
to Vincent Snijders: I am not sure, but maybe this is related. Since the beginning of July the listbox test…
Marco van de Voort wrote 22 lines
> I am not sure, but maybe this is related. > > Since the beginning of July the listbox test program stopped > working. I didn't have time to investigate further. Neli and I debugged it a bit, and it seems to be an ansistring initialisation problem. Maybe it is, maybe not (only Neli had the AV, I didn't, he'll research it more deeply later), but the problem we did find was a problem anyway, so I'd like to warn for it. The problem is near win32callback.inc:148 (version 1.41) var LMessage : TLMessage; With PLMInsertText(@LMessage)^ Do Begin [..] Newtext:=string(lparam); [..] end;

Eeeekkk... seeing this, I can imagine the errors Micha described. I don't know where it came from, but ppl, please be carefull. Don't mess with strings (and Interfaces and Dynamic arrays), they are dynamic and reference counted.
Please make in these cases the string still exsists.

Example:

function Good: String;
var
   S: String;
begin
   S := 'SomeText;  // The refcount of the sting becomes 1
   Result := S;     // The refcount of the sting becomes 2
end;               // S is cleared ->
                    // The refcount of the string becomes 1
                    // The string is still avaiable outside the function
function Bad: Integer;
var
   S: String;
begin
   S := 'SomeText;        // The refcount of the sting becomes 1
   Result := Integer(S);  // Strings are infact pointers, but this
                          // has no effect on the refcount
end;                     // S is cleared ->
                          // The refcount of the string becomes 0
                          // The string is cleared
                          // The result is useless

Once you start casting, you disable all nice compiler logic, and *you* have to make sure what you do.

Show quoted text 13 lines
There are at least one, and possible _two_ bugs in this single line. First, because of the construct with the pointer and the @ in the WITH clause, newtext isn't initialised to zero (as ansistrings should) The declaration of LMessage should do that, but "TLMessage" doesn't contain the ansistring field, so it is not initialised to zero. When nextext is used, it is decreased in ref count, and since the random value points into deep space, so accessing the ref count via the pointer can produce an AV. It can be remedied by initing newtest to zero: integer(newtext):=0; // pchar(newtext):=nil isn't allowed.

Why isnt the LMessage declared as TLMInsertText anyway ?

Show quoted text 24 lines
The second problem is if you think what the assignment means: newtext:=string(lparam); With newtext=ansistring (which is a pointer type), and lparam is of type longint (or integer) it says: "type cast the integer value of lparam to a pointer. Store that pointer in the place "newtext" This while "lparam" is a pchar, IOW the pchar to ansistring conversion doesn't take place. So the correct typecast is: newtext:=pchar(lparam); Which says. "Lparam" is actually of type pchar, and assignment to an ansistring will trigger proper conversion. But in general I'd advise to keep such structures (as in lmessage etc) pchar only, to avoid both problems a bit. You can still assign the pchars to local "ansistring" variables.

But keep the lifetime of the string in mind. Cast a string to a PChar and post it as a message will never ever work and allways lead to the most unpredictable and hard to trace errors.

Marc (funny, today at work I had the same case)

Reply by email

Vincent Snijders
to Micha Nelissen: Currently, lazarus crashes continually on my box. Backtrace: #0 $006b2ed9 in…

Hi,

I am not sure, but maybe this is related.

Since the beginning of July the listbox test program stopped working. I didn't have time to investigate further.

Regards,
Vincent.

Show quoted text 36 lines
Hi, Currently, lazarus crashes continually on my box. Backtrace: #0 $006b2ed9 in SYSWIN32$$_ANSISTR_DECR_REF$POINTER () #1 $006b2f88 in SYSWIN32$$_ANSISTR_ASSIGN$POINTER$POINTER () #2 $0067a278 in WINDOWPROC (WINDOW=5964548, MSG=330, WPARAM=0, LPARAM=50054128) at win32callback.inc:148 #3 $77e12ca8 in _size_of_stack_reserve__ () #4 $77e14764 in _size_of_stack_reserve__ () #5 $77e273a2 in _size_of_stack_reserve__ () #6 $77fa15ef in ?? () #7 $77e153a1 in _size_of_stack_reserve__ () #8 $0068302b in TWIN32OBJECT__SENDMESSAGE (HANDLEWND=5964548, #MSG=330, WPARAM=0, LPARAM=50054128, this=$876dd0) at win32winapi.inc:1940 #9 $00662ef5 in SENDMESSAGE (HANDLEWND=5964548, MSG=330, WPARAM=0, LPARAM=50054128) at winapi.inc:950 Is this a bug in the ansistring functions? Sometimes it starts bugging me, then mysteriously disappears again. But now it doesn't disappear :(. Any hints, please? Thanks, Micha. _________________________________________________________________ To unsubscribe: mail with "unsubscribe" as the Subject archives at http://www.lazarus.freepascal.org/mailarchives

Reply by email

Marco van de Voort
to Marc Weustink: Eeeekkk... seeing this, I can imagine the errors Micha described. I don't know where it…
Show quoted text 15 lines
At 23:53 25-7-2003 +0200, Marco van de Voort wrote: >First, because of the construct with the pointer and the @ in the WITH >clause, newtext isn't initialised to zero (as ansistrings should) > >The declaration of LMessage should do that, but "TLMessage" doesn't contain >the ansistring field, so it is not initialised to zero. When nextext is >used, it is decreased in ref count, and since the random value points into >deep space, so accessing the ref count via the pointer can produce an AV. > >It can be remedied by initing newtest to zero: > >integer(newtext):=0; // pchar(newtext):=nil isn't allowed. Why isnt the LMessage declared as TLMInsertText anyway ?

It seems to depend on a CASE statement if the base type is used.

That is also dangerous if TLMInsertText is larger than LMessage (and it is), and field beyond the range defined by LMessage are used.

But keep the lifetime of the string in mind. Cast a string to a PChar and post it as a message will never ever work and allways lead to the most unpredictable and hard to trace errors.

It is one of the problems of Pascal (at least Borland dialects), that conversion and cast are noted the same. Please keep in mind that they are NOT the same, specially in the case of automated types.

What's the difference?
- a typecast is like changing typing for a memory location.
- a conversion truely converts a type from one to another.

A pchar to ansistring is a conversion (the data needed for automising the type needs to be added). However this is an conversion

var p:pchar;
    s:ansistring;
s:=p;

And this is not:

s:=string(p);

(one of the errors in the original snippet)

The other way around (pchartyped:=ansistringtyped) isn't  allowed as conversion,
only as cast.
pchartyped:=pchar(ansistringtyped);

This construct is also somewhat dangerous.

The pchar becomes a reference to the content of the ansistring. The ansistring will still disappear when it goes out of scope. (and pchar will remain pointing to released memory) Any modification to the pchar will affect the ansistring.

Reply by email

Marc Weustink
to Marc Weustink: Eeeekkk... seeing this, I can imagine the errors Micha described. I don't know where it…
Marco van de Voort wrote 11 lines
The other way around (pchartyped:=ansistringtyped) isn't allowed as conversion, only as cast. pchartyped:=pchar(ansistringtyped); This construct is also somewhat dangerous. The pchar becomes a reference to the content of the ansistring. The ansistring will still disappear when it goes out of scope. (and pchar will remain pointing to released memory) Any modification to the pchar will affect the ansistring.

Ah, thats another thing. Ansistrings share the same data (they are in fact pointers) if they are assigned, until they are changed. Casting to PChar may have strange side effects

Example

Good:

a, b : String

   A := 'Some Text';   // A points to 'Some Text'
   B := A;             // B points to the same text
   B := 'Other Text';  // A new instance ot B is created
                       // and it points to 'Other Text'
                       // A has still 'Some Text'

Bad:

a, b : String

   A := 'Text';       // A points to 'Text'
   B := A;            // B points to the same text
   PChar(B)^ := 'N';  // Now B has the text 'Next'
                      // but since the data was shared with A
                      // A has also the text 'Next'

Marc

Reply by email

Marco van de Voort
to Vincent Snijders: I am not sure, but maybe this is related. Since the beginning of July the listbox test…
I am not sure, but maybe this is related. Since the beginning of July the listbox test program stopped working. I didn't have time to investigate further.

Neli and I debugged it a bit, and it seems to be an ansistring initialisation problem.

Maybe it is, maybe not (only Neli had the AV, I didn't, he'll research it more deeply later), but the problem we did find was a problem anyway, so I'd like to warn for it.

The problem is near win32callback.inc:148 (version 1.41)

var LMessage : TLMessage;
 With PLMInsertText(@LMessage)^ Do
  Begin
   [..]
    Newtext:=string(lparam);
   [..]
  end;

There are at least one, and possible _two_ bugs in this single line.

First, because of the construct with the pointer and the @ in the WITH clause, newtext isn't initialised to zero (as ansistrings should)

The declaration of LMessage should do that, but "TLMessage" doesn't contain the ansistring field, so it is not initialised to zero. When nextext is used, it is decreased in ref count, and since the random value points into deep space, so accessing the ref count via the pointer can produce an AV.

It can be remedied by initing newtest to zero:

integer(newtext):=0;		// pchar(newtext):=nil isn't allowed.

The second problem is if you think what the assignment means:

newtext:=string(lparam);

With newtext=ansistring (which is a pointer type), and lparam is of type longint (or integer) it says:

"type cast the integer value of lparam to a pointer. Store that pointer in the place "newtext"

This while "lparam" is a pchar, IOW the pchar to ansistring conversion doesn't take place.

So the correct typecast is:

newtext:=pchar(lparam);

Which says. "Lparam" is actually of type pchar, and assignment to an ansistring will trigger proper conversion.

But in general I'd advise to keep such structures (as in lmessage etc) pchar only, to avoid both problems a bit.

You can still assign the pchars to local "ansistring" variables.

Reply by email