[Lazarus] Weird object variables access [SOLVED] - Delphi mode bug!
giuliano.colla at fastwebnet.it
Tue Oct 24 13:56:43 CEST 2017
Il 23/10/2017 22:57, Mattias Gaertner via Lazarus ha scritto:
> Check if 'Self' inside SendMessage is the right instance.
Yes, you're right, that's what clarifies the issue. When it works, Self
is a TFORM1 object, when it fails, Self is just Nil.
But now it's also clear why this happens.
The issue has nothing to do with thread code, it has to do with Delphi
mode and Delphi syntax! It is either an fpc Delphi mode bug, or a Delphi
bug, kept in fpc for "compatibility".
The full story is that this application has been originally written more
than 20 years ago, using Delphi 3. Then it was updated to Delphi 5, and
subsequently ported to Lazarus, but keeping the Delphi mode, to minimize
SendMessage can be called in two ways: either directly from another main
thread method, or somehow indirectly (always from another main thread
method), through a NextProc value fetched from a queue.
The application is used to upload a program to an embedded processor.
The main thread reads by chunks from the disk the program to be uploaded
and pushes into a queue what should be done next (send the first header,
send an intermediate chunk, send the last chunk, send the program
version and date, etc). At the good time, the appropriate method is
fetched from the queue and called; in turn it calls SendMessage to do
the actual job.
When SendMessage is called directly from another method, the Self
instance is correct, when it is called indirectly by a fetching from the
queue the method to call, Self is just Nil.
Now the catch is that the queue used is just a queue of pointers, while
here we're dealing with procedures of object. This is legal with Delphi
syntax, while it is forbidden in ObjFpc. When I tried to see if the
problem was originated by Delphi mode, and changed to objfpc mode, it
turned out that there was no way to make it compile. But just changing
my queue from a queue of pointers to a queue of TProc (TProc = procedure
of object) fixes the issue: it compiles, it works, Self is correct,
there's no need to qualify the identifier, and all is well.
The moral of the story is: in Delphi mode you can assign a procedure of
object to a pointer, and the compiler doesn't complain, but it is wrong,
because when you call your method through this pointer, the method is
executed, but it's unaware of the data space of the object it belongs
to, even if it's called from another method of the same object! If the
method doesn't access variables of the object, everything appears to
work, but if it does the program simply crashes.
I will try to see if the same occurs also in Delphi, to understand if
it's a Delphi bug or an fpc bug.
More information about the Lazarus