Recent

Author Topic: TFPGMap issue after upgrade to FPC 3.2.0  (Read 1209 times)

antispam88

  • Jr. Member
  • **
  • Posts: 62
TFPGMap issue after upgrade to FPC 3.2.0
« on: April 11, 2021, 11:28:59 pm »
Hi,

we are still using FPC 3.0.4 and Lazarus 2.0.8 (Win x86 + x64/Linux x64/Linux ARM) for our working projects.
Now we want to upgrade to the latest versions (FPC 3.2.0 + Lazarus 2.0.12).
After setting up the environment I had to adjust the code with some overload keywords which the new version claims.
Then to code compiled but failed regarding TFPGMap.
Freeing a map throws an "Access violation" in line 1561 of fgl.pp in the function DEREF.
I'm accessing the values using the Data property and copying items between maps using the Assign procedure.
I only found in the user changes of FPC 3.2.0 regarding FGL that the declaration of typ TTypeList has changed.
Does this cause our problems?

Here is an example of our map declaration:
Code: Pascal  [Select][+][-]
  1. type
  2. ITest = interface(IUnknown)
  3. function GetTestFunction: integer;
  4. end;
  5. TTestMap = specialize TFPGMap<string, ITest>;

We are looking forward to receive any hints or solutions.
Thx.

Best regards,
antispam88

jamie

  • Hero Member
  • *****
  • Posts: 4452
Re: TFPGMap issue after upgrade to FPC 3.2.0
« Reply #1 on: April 12, 2021, 04:08:12 am »
You need to pay closer attention to the error message..

That line number is pointing to the start of a finalize(TKey(item^)…… for which the Item, which is a pointer, could be NIL ? or in your case the string that TKEY is looking at could be NIL instead of pointing to a valid empty string and finalize is choking on it.

 The Error message should show an access violation at Address xxxxxx the address is important.


 or you found a bug in the compiler with the managed operators. Who knows.
The only true wisdom is knowing you know nothing

egsuh

  • Hero Member
  • *****
  • Posts: 723
Re: TFPGMap issue after upgrade to FPC 3.2.0
« Reply #2 on: April 12, 2021, 05:09:35 am »
Your data type is Interface, not any object. What if the interfaced object is not created?

PascalDragon

  • Hero Member
  • *****
  • Posts: 2979
  • Compiler Developer
Re: TFPGMap issue after upgrade to FPC 3.2.0
« Reply #3 on: April 12, 2021, 09:25:14 am »
We are looking forward to receive any hints or solutions.

Can you provide a more complete example?

antispam88

  • Jr. Member
  • **
  • Posts: 62
Re: TFPGMap issue after upgrade to FPC 3.2.0
« Reply #4 on: April 13, 2021, 11:12:41 am »
As I mentioned in the first post, our code is working in 3.0.4/2.0.8 without any errors.
All interfaces are initialized.
My thought was that maybe someone has already come across this problem.

Unfortunately I can't post our company's project, but I try to create a demo project.
Best regards,
antispam88

engkin

  • Hero Member
  • *****
  • Posts: 2701
Re: TFPGMap issue after upgrade to FPC 3.2.0
« Reply #5 on: April 13, 2021, 12:43:22 pm »
"For reference counted interface objects, TFPGMapInterfacedObjectData must be used."

antispam88

  • Jr. Member
  • **
  • Posts: 62
Re: TFPGMap issue after upgrade to FPC 3.2.0
« Reply #6 on: April 22, 2021, 10:06:33 am »
I have now changed TFPGMap to TFPGMapInterfacedObject and TFPGList to TFPGInterfacedObjectList.
So I was able to start our application.
But when I adjust the items of one of our TFPGInterfacedObjectList instances I'm getting an access violation because of accessing a freeed object (reference count is 0).

I have attached an example. The TFPGInterfacedObjectList is doing same as in our application. The TFPGList is working as expected.
Code: Pascal  [Select][+][-]
  1. ITestInterface = interface(IUnknown)
  2.     ['{734C54C2-BF68-4140-8DB4-8F1416A0545C}']
  3.     function GetName: string;
  4.     procedure SetName(const aname: string);
  5.     function GetRefCount: integer;
  6.   end;
  7.  
  8.   TTestInterfacedList = specialize TFPGInterfacedObjectList<ITestInterface>;
  9.   TTestStandardList = specialize TFPGList<ITestInterface>;
  10.  
  11.   TTestObject = class(TInterfacedObject, ITestInterface)
  12.   protected
  13.     _name: string;
  14.   public
  15.     function GetName: string;
  16.     procedure SetName(const aname: string);
  17.     function GetRefCount: integer;
  18.   end;
  19. ...
  20. procedure TForm1.BtInitInterfacedClick(Sender: TObject);
  21. var
  22.   i: integer;
  23. begin
  24.   GroupBox2.Enabled := False;
  25.   for i := 0 to 15 do
  26.   begin
  27.     WriteLn('Init: ', _interface1.GetName, ' ', _interface1.GetRefCount);
  28.     _test_interfaced_list.Add(_interface1);
  29.   end;
  30.   BtAdjustInterfaced.Enabled := True;
  31. end;
  32.  
  33. procedure TForm1.BtAdjustStandardClick(Sender: TObject);
  34. var
  35.   interface_cur: ITestInterface;
  36.   interface_new: ITestInterface;
  37.   i: integer;
  38. begin
  39.   for i := 0 to 15 do
  40.   begin
  41.     WriteLn('Adjust: ', _test_standard_list.Items[i].GetName, ' ',
  42.       _test_standard_list.Items[i].GetRefCount);
  43.     interface_cur := _test_standard_list.Items[i];
  44.     if (i < 8) or (i > 11) then
  45.     begin
  46.       interface_new := TTestObject.Create;
  47.       interface_new.SetName('interface ' + IntToStr(i));
  48.       _test_standard_list.Items[i] := interface_new;
  49.     end
  50.     else
  51.     begin
  52.       _test_standard_list.Items[i] := _interface1;
  53.     end;
  54.     interface_cur := nil;
  55.   end;
  56. end;
  57.  
  58. procedure TForm1.BtAdjustInterfacedClick(Sender: TObject);
  59. var
  60.   interface_cur: ITestInterface;
  61.   interface_new: ITestInterface;
  62.   i: integer;
  63. begin
  64.   for i := 0 to 15 do
  65.   begin
  66.     try
  67.       WriteLn('Adjust: ', _test_interfaced_list.Items[i].GetName, ' ',
  68.         _test_interfaced_list.Items[i].GetRefCount);
  69.       interface_cur := _test_interfaced_list.Items[i];
  70.       if (i < 8) or (i > 11) then
  71.       begin
  72.         interface_new := TTestObject.Create;
  73.         interface_new.SetName('interface ' + IntToStr(i));
  74.         _test_interfaced_list.Items[i] := interface_new;
  75.       end
  76.       else
  77.       begin
  78.         _test_interfaced_list.Items[i] := _interface1;
  79.       end;
  80.       interface_cur := nil;
  81.     except
  82.       on e: Exception do
  83.       begin
  84.         WriteLn(e.Message);
  85.         raise;
  86.       end;
  87.     end;
  88.   end;
  89. end;
  90.  
  91. procedure TForm1.BtInitStandardClick(Sender: TObject);
  92. var
  93.   i: integer;
  94. begin
  95.   GroupBox1.Enabled := False;
  96.   for i := 0 to 15 do
  97.   begin
  98.     WriteLn('Init: ', _interface1.GetName, ' ', _interface1.GetRefCount);
  99.     _test_standard_list.Add(_interface1);
  100.   end;
  101.   BtAdjustStandard.Enabled := True;
  102. end;

Do I use the TFPGInterfacedObjectList in a correct way?

Best regards,
antispam88

FPC: 3.2.0
Lazarus: 2.0.12
Win 10 x64

Thaddy

  • Hero Member
  • *****
  • Posts: 10786
Re: TFPGMap issue after upgrade to FPC 3.2.0
« Reply #7 on: April 22, 2021, 10:36:41 am »
Is the interface COM or CORBA?

antispam88

  • Jr. Member
  • **
  • Posts: 62
Re: TFPGMap issue after upgrade to FPC 3.2.0
« Reply #8 on: April 22, 2021, 11:25:32 am »
{$interfaces CORBA} is not defined, so I assume it is COM, or?

ASerge

  • Hero Member
  • *****
  • Posts: 1781
Re: TFPGMap issue after upgrade to FPC 3.2.0
« Reply #9 on: April 22, 2021, 07:01:31 pm »
A simpler example:
Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}
  2. {$APPTYPE CONSOLE}
  3.  
  4. uses SysUtils, fgl;
  5.  
  6. type
  7.   TIntfObjectList = specialize TFPGInterfacedObjectList<IInterface>;
  8.   //TIntfObjectList = specialize TFPGList<IInterface>;
  9.  
  10. procedure Test;
  11. var
  12.   SomeInstance: IInterface;
  13.   List: TIntfObjectList;
  14.   i: Integer;
  15. begin
  16.   SomeInstance := TInterfacedObject.Create;
  17.   List := TIntfObjectList.Create;
  18.   try
  19.     for i := 0 to 2 do
  20.     begin
  21.       List.Add(SomeInstance);
  22.       Writeln(i, ': ', (SomeInstance as TInterfacedObject).RefCount);
  23.     end;
  24.     Writeln;
  25.     for i := 0 to 2 do
  26.     begin
  27.       Writeln(i, ': ', (SomeInstance as TInterfacedObject).RefCount);
  28.       List[i] := nil;
  29.     end;
  30.   finally
  31.     List.Free;
  32.   end;
  33. end;
  34.  
  35. begin
  36.   try
  37.     Test;
  38.   except
  39.     on E: Exception do
  40.       Writeln(E.Message);
  41.   end;
  42.   Readln;
  43. end.

engkin

  • Hero Member
  • *****
  • Posts: 2701
Re: TFPGMap issue after upgrade to FPC 3.2.0
« Reply #10 on: April 23, 2021, 05:53:43 am »
I think I found the bug. This procedure:
Code: Pascal  [Select][+][-]
  1. procedure TFPGInterfacedObjectList.CopyItem(Src, Dest: Pointer);
  2. begin
  3.   if Assigned(Pointer(Dest^)) then
  4.     T(Dest^)._Release;
  5.   Pointer(Dest^) := Pointer(Src^);
  6.   if Assigned(Pointer(Dest^)) then
  7.     T(Dest^)._AddRef;
  8. end;

should increase the reference count of Src before reducing it for Dest, as in:
Code: Pascal  [Select][+][-]
  1. procedure TFPGInterfacedObjectList.CopyItem(Src, Dest: Pointer);
  2. begin
  3.   if Assigned(Pointer(Src^)) then
  4.     T(Src^)._AddRef;
  5.   if Assigned(Pointer(Dest^)) then
  6.     T(Dest^)._Release;
  7.   Pointer(Dest^) := Pointer(Src^);
  8. end;

To test, copy fgl file to your project and change the file name and the unit name to something else like fgl2 and make the above mentioned modification. Finally, change the name of the unit in
 USES section in your project as well.
« Last Edit: April 23, 2021, 05:56:24 am by engkin »

antispam88

  • Jr. Member
  • **
  • Posts: 62
Re: TFPGMap issue after upgrade to FPC 3.2.0
« Reply #11 on: April 23, 2021, 08:00:49 am »
Changing the method
Quote
    procedure TFPGInterfacedObjectList.CopyItem(Src, Dest: Pointer);
    begin
      if Assigned(Pointer(Src^)) then
        T(Src^)._AddRef;
      if Assigned(Pointer(Dest^)) then
        T(Dest^)._Release;
      Pointer(Dest^) := Pointer(Src^);
    end;

has no effect on my example.
I have attached the changed project as well as the output of the original fgl and the changed fgl2.

Best regards,
antispam88

engkin

  • Hero Member
  • *****
  • Posts: 2701
Re: TFPGMap issue after upgrade to FPC 3.2.0
« Reply #12 on: April 23, 2021, 09:19:48 am »
You are right, I have other changes in fgl I need to clean and make sure not to replace one bug with another. Your project might be a good way to test.

engkin

  • Hero Member
  • *****
  • Posts: 2701
Re: TFPGMap issue after upgrade to FPC 3.2.0
« Reply #13 on: April 23, 2021, 09:28:23 am »
Please test the attached file

antispam88

  • Jr. Member
  • **
  • Posts: 62
Re: TFPGMap issue after upgrade to FPC 3.2.0
« Reply #14 on: April 23, 2021, 11:39:20 am »
The Init and the Adjust methods are now working.
But I have now included a Free method, which is not freeing the items - the TFPGList version does.
Best regards,
antispam88

 

TinyPortal © 2005-2018