Hi!
I've got another problem with the compiler. Stripped down the problem, it comes out that the compiler doesn't work correctly with overloaded methods.
For example: Serial transmission of data, a base class: CSerialInterface
which implements some methods for sending.
Send(Buf:Pointer;Length:LongInt); virtual; abstract;
Send(St:String); virtual;
Send(Buf:CCharBuffer); virtual;(CCharBuffer is a class which is a "smart" char buffer)
Each serial interface type gets a descent class.
Type CRS232 = class(CSerialInterface) ... End;
Type CRS485 = class(CSerialInterface) ... End;
Type CRS422 = class(CSerialInterface) ... End;
(as examples). They only implement Send(Buf:Pointer;Length:LongInt);
And CSerialInterface implements the other Send methods which are only
wrappers for the above one (look at "virtual" and "virtual abstract"
declarations in CSerialInterface):
Procedure CSerialInterface.Send(St:String);
Begin
Send(@St[1],Length(St));
End;
(and analogous for the CCharBuffer method).CRS232 now has 3 Send methods:
Send(Buf:Pointer;Length:LongInt); { implemented there } Send(St:String); { inherited from CSerialInterface } Send(Buf:CCharBuffer); { inherited from CSerialInterface }
Let's now look at the main program:
Var RS232 : CRS232;
Test : CSerialInterface;
St : String;
Begin
St := 'Hello World!';
RS232 := CRS232.Create;
RS232.Send(@St[1],Length(St)); { <-- works! }
RS232.Send(St); { compiler complains [1] }
Test := RS232;
Test.Send(St); { ugly crash [2] }
End.[1] the compiler complains
Error: Wrong amount of parameters specified
what means, that it it didn't find the Send(St:String) method. Despite it is inherited!!!
[2] here the compiler seems to have a problem with the VMT and the location each overloaded method gets in the VMT. First it calls CSerialInterface.Send(St:String) (which is called correct). This method then calls Send(Buf:Pointer;Length:LongInt).
Therefore the VMT was invented to find the "most actual" method. CSerialInterface.Send(St:String) gets the VMT of CRS232 (as hidden parameter) and so calls CRS232.Send(Buf:Pointer;Length:LongInt).
Paff! Crash! The compiler seems to use another one of the 3 Send methods from the VMT. Namely the Send(St:String). Which calls itself recursively. And with the wrong parameter and even the wrong parameter count.
I didn't try exactly the setup described here. Please have a look at the attached file. It contains a few units demonstrating the problem.
Please use "ulimit -s 256" before executing "./bar". This limits the stack and prevents a complete crash of your computer.
BTW: I'm using
Free Pascal Compiler version 1.0.6 [2002/08/10] for i386 in my Debian Linux (sid).
BTW: Strange: sometimes it has the problem as described and sometimes it even doesn't identify the Test.Send(St) correctly.
Please try using "fpc bar.pas" and "fpc -B bar.pas" several times. Then the problem occurs in different ways. Strange.
Bye
Hansi
