[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