[Lazarus] Weird object variables access [SOLVED] - Delphi mode bug!

Giuliano Colla 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 
the changes.

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.

Giuliano



More information about the Lazarus mailing list