[Lazarus] Access violation in SYSGETMEM_FIXED - memory corruption?

Martin lazarus at mfriebe.de
Thu May 26 23:58:56 CEST 2011


Here is what happens


procedure TfrmFileAssoc.btnAddNewTypeClick(Sender: TObject);
begin
   edtIconFileName.Text:= TExtAction(Exts.Items[0]).Icon;
end;
procedure TfrmFileAssoc.edtIconFileNameChange(Sender: TObject);
begin
   TExtAction(Exts.Items[0]).Icon := GenName; //DateTimeToStr(Now);
end;


1) btnAddNewTypeClick.
Takes the string from ExtAction(Exts.Items[0]).Icon;
This string has a ref-count of 1 (not sure why it shows 2 in your debug)

2) SetText(const AValue: String)
because AValue is constant, it is not expected to change. The compiler 
optimizes the code, the ref-count is not increased. This does save the 
need to insert a hidden try-finally block, which otherwhis would be 
requiredm, to ensure that the refcout was decreased at the end of 
SetText (even if an exception occurred). Those implicit tr-finally 
blocks have a noticeable effect on speed.

3) Going through RealSetText, but then calling you event handler: 
edtIconFileNameChange

4) edtIconFileNameChange
Releases the string referred to by ExtAction(Exts.Items[0]).Icon;
  => memory is freed
AValue now points to freed memory => it didn't expect that the value was 
changed.

Since AValue points to freed memory, it will crash on the next attempt 
to use it.


----
This is actually part of the definition  of "const" for parameters.

const does mean that you as programmer (or in this case the person who 
wrote it) declares that no code anywhere will change the value of this 
variable (which includes calling code)

As a side effect, if using code, the compiler will give you an error, if 
you try to modify it inside that procedure. Because the compiler can 
detect that, and because you promised the compiler not to do it.
But the compiler expects that promise to be kept outside the given 
procedure too.


You code does not keep the promise, which some one else made.... Ouch.

Obviously it could be argued, the LCL should not make such promises. 
It's a decision to be made (and probably to be reviewed now)






On 26/05/2011 22:21, cobines wrote:
> I have added some debugging text in two functions that set text to a
> control: TWinControl.RealSetText and widgetset specific
> TWin32WSWinControl.SetText (like in attached diff).
>
> This is a log from execution of a program when it crashes:
>
> TWin32WSWinControl.SetText before 0005FBD8 refcount=2 size=17
> TWin32WSWinControl.SetText after  0005FBD8 refcount=2 size=17
> TWin32WSWinControl.SetText before 00066D10 refcount=3 size=3
> TWin32WSWinControl.SetText after  00066D10 refcount=3 size=3
> TWinControl.RealSetText before    00526F18 refcount=-1 size=15
> TWin32WSWinControl.SetText before 00526F18 refcount=-1 size=15
> TWin32WSWinControl.SetText after  00526F18 refcount=-1 size=15
> TWinControl.RealSetText after     00526F18 refcount=-1 size=15
> TWinControl.RealSetText before    0007F8A0 refcount=1 size=55
> TWin32WSWinControl.SetText before 0007F8A0 refcount=1 size=55
> TWin32WSWinControl.SetText after  0007F8A0 refcount=522612 size=0
> TWinControl.RealSetText after     0007F8A0 refcount=522612 size=0
> TWinControl.RealSetText before    00056A80 refcount=1 size=17
> TWin32WSWinControl.SetText before 00056A80 refcount=1 size=17
> TWin32WSWinControl.SetText after  00056A80 refcount=355076 size=0
> TWinControl.RealSetText after     00056A80 refcount=355076 size=354980
>
> In TWin32WSWinControl.SetText there is corruption of the string record
> (but the contents are fine).
>
> Now, if I change
>    procedure TControl.SetText(const Value: TCaption);
> to
>    procedure TControl.SetText(Value: TCaption);
>
> everything is fine:
>
> TWin32WSWinControl.SetText before 0005FBD8 refcount=2 size=17
> TWin32WSWinControl.SetText after  0005FBD8 refcount=2 size=17
> TWin32WSWinControl.SetText before 00066D10 refcount=3 size=3
> TWin32WSWinControl.SetText after  00066D10 refcount=3 size=3
> TWinControl.RealSetText before    00526F18 refcount=-1 size=15
> TWin32WSWinControl.SetText before 00526F18 refcount=-1 size=15
> TWin32WSWinControl.SetText after  00526F18 refcount=-1 size=15
> TWinControl.RealSetText after     00526F18 refcount=-1 size=15
> TWinControl.RealSetText before    0007F8A0 refcount=2 size=55
> TWin32WSWinControl.SetText before 0007F8A0 refcount=2 size=55
> TWin32WSWinControl.SetText after  0007F8A0 refcount=1 size=55
> TWinControl.RealSetText after     0007F8A0 refcount=1 size=55
> TWinControl.RealSetText before    0007F910 refcount=2 size=53
> TWin32WSWinControl.SetText before 0007F910 refcount=2 size=53
> TWin32WSWinControl.SetText after  0007F910 refcount=1 size=53
> TWinControl.RealSetText after     0007F910 refcount=1 size=53
>
> --
> cobines
>
>
> --
> _______________________________________________
> Lazarus mailing list
> Lazarus at lists.lazarus.freepascal.org
> http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20110526/750e0df4/attachment-0003.html>


More information about the Lazarus mailing list