Recent

Author Topic: Bug TFPGInterfacedObjectList??  (Read 212 times)

J-23

  • Full Member
  • ***
  • Posts: 108
Bug TFPGInterfacedObjectList??
« on: October 28, 2020, 10:14:44 pm »
Hello,

I haven't used TFPGInterfacedObjectList for a long time and now I need such a list.

Everything works fine theoretically, but I think I ran into a bug in the FPC.

I have a code: (Work OK)
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, fgl;
  9.  
  10. type
  11.   ITest = interface(IUnknown)
  12.   ['{1416EB7E-39B0-4134-BA20-F363D0B8C476}']
  13.    procedure Test;
  14.   end;
  15.  
  16. type
  17.   TListInterface = specialize TFPGInterfacedObjectList<ITest>;
  18.  
  19. type
  20.  
  21.   { TTestClass }
  22.  
  23.   TTestClass = class(TInterfacedObject, ITest)
  24.     procedure Test;
  25.   end;
  26.  
  27. type
  28.  
  29.   { TForm1 }
  30.  
  31.   TForm1 = class(TForm)
  32.     procedure FormCreate(Sender: TObject);
  33.     procedure FormDestroy(Sender: TObject);
  34.   private
  35.     FListInterface: TListInterface;
  36.     FTestClass: TTestClass;
  37.   public
  38.      procedure ExecuteInterface(Test: ITest);
  39.   end;
  40.  
  41. var
  42.   Form1: TForm1;
  43.  
  44. implementation
  45.  
  46. {$R *.lfm}
  47.  
  48. { TTestClass }
  49.  
  50. procedure TTestClass.Test;
  51. begin
  52.  
  53. end;
  54.  
  55. { TForm1 }
  56.  
  57. procedure TForm1.FormCreate(Sender: TObject);
  58. begin
  59.   FListInterface := TListInterface.Create;
  60.  
  61.   FTestClass := TTestClass.Create;
  62.   FListInterface.Add(FTestClass);
  63. end;
  64.  
  65. procedure TForm1.FormDestroy(Sender: TObject);
  66. begin
  67.   FListInterface.Free;
  68. end;
  69.  
  70. procedure TForm1.ExecuteInterface(Test: ITest);
  71. begin
  72.  
  73. end;
  74.  
  75. end.                                                          
  76.  

But the code below causes an error. (I think he shouldn't)

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, fgl;
  9.  
  10. type
  11.   ITest = interface(IUnknown)
  12.   ['{1416EB7E-39B0-4134-BA20-F363D0B8C476}']
  13.    procedure Test;
  14.   end;
  15.  
  16. type
  17.   TListInterface = specialize TFPGInterfacedObjectList<ITest>;
  18.  
  19. type
  20.  
  21.   { TTestClass }
  22.  
  23.   TTestClass = class(TInterfacedObject, ITest)
  24.     procedure Test;
  25.   end;
  26.  
  27. type
  28.  
  29.   { TForm1 }
  30.  
  31.   TForm1 = class(TForm)
  32.     procedure FormCreate(Sender: TObject);
  33.     procedure FormDestroy(Sender: TObject);
  34.   private
  35.     FListInterface: TListInterface;
  36.     FTestClass: TTestClass;
  37.   public
  38.      procedure ExecuteInterface(Test: ITest);
  39.   end;
  40.  
  41. var
  42.   Form1: TForm1;
  43.  
  44. implementation
  45.  
  46. {$R *.lfm}
  47.  
  48. { TTestClass }
  49.  
  50. procedure TTestClass.Test;
  51. begin
  52.  
  53. end;
  54.  
  55. { TForm1 }
  56.  
  57. procedure TForm1.FormCreate(Sender: TObject);
  58. begin
  59.   FListInterface := TListInterface.Create;
  60.  
  61.   FTestClass := TTestClass.Create;
  62.   ExecuteInterface(FTestClass);
  63.   FListInterface.Add(FTestClass);
  64. end;
  65.  
  66. procedure TForm1.FormDestroy(Sender: TObject);
  67. begin
  68.   FListInterface.Free;
  69. end;
  70.  
  71. procedure TForm1.ExecuteInterface(Test: ITest);
  72. begin
  73.  
  74. end;
  75.  
  76. end.                                                                
  77.  

The only difference is this line
Code: Pascal  [Select][+][-]
  1. ExecuteInterface(FTestClass);

J-23

  • Full Member
  • ***
  • Posts: 108
Re: Bug TFPGInterfacedObjectList??
« Reply #1 on: October 29, 2020, 03:08:00 am »
Eh ... memory plays tricks :)

Code: Pascal  [Select][+][-]
  1. TInterfaceList

ASerge

  • Hero Member
  • *****
  • Posts: 1694
Re: Bug TFPGInterfacedObjectList??
« Reply #2 on: October 29, 2020, 09:56:09 pm »
The only difference is this line
Code: Pascal  [Select][+][-]
  1. ExecuteInterface(FTestClass);
The "ExecuteInterface" and "FListInterface.Add" methods are expected an interface parameter, but you pass the class parameter. An implicit conversion is made, but you do not control the lifetime, so the object (this is the interface) by the reference counter "dies" on the first call.
There are different solutions.
1. Skip a reference counter in methods:
  procedure ExecuteInterface(const Test: ITest);
2. Explicit add reference:
  ExecuteInterface(FTestClass as ITest);
3. Use a variable of the desired type (the safest solution):
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. var
  3.   LTest: ITest;
  4. begin
  5.   FListInterface := TListInterface.Create;
  6.   FTestClass := TTestClass.Create;
  7.   LTest := FTestClass;
  8.   ExecuteInterface(LTest);
  9.   FListInterface.Add(LTest);
  10. end;

 

TinyPortal © 2005-2018