Lazarus

Free Pascal => General => Topic started by: antispam88 on April 11, 2021, 11:28:59 pm

Title: TFPGMap issue after upgrade to FPC 3.2.0
Post by: antispam88 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
Title: Re: TFPGMap issue after upgrade to FPC 3.2.0
Post by: jamie 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.
Title: Re: TFPGMap issue after upgrade to FPC 3.2.0
Post by: egsuh on April 12, 2021, 05:09:35 am
Your data type is Interface, not any object. What if the interfaced object is not created?
Title: Re: TFPGMap issue after upgrade to FPC 3.2.0
Post by: PascalDragon 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?
Title: Re: TFPGMap issue after upgrade to FPC 3.2.0
Post by: antispam88 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
Title: Re: TFPGMap issue after upgrade to FPC 3.2.0
Post by: engkin on April 13, 2021, 12:43:22 pm
"For reference counted interface objects, TFPGMapInterfacedObjectData must be used."
Title: Re: TFPGMap issue after upgrade to FPC 3.2.0
Post by: antispam88 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
Title: Re: TFPGMap issue after upgrade to FPC 3.2.0
Post by: Thaddy on April 22, 2021, 10:36:41 am
Is the interface COM or CORBA?
Title: Re: TFPGMap issue after upgrade to FPC 3.2.0
Post by: antispam88 on April 22, 2021, 11:25:32 am
{$interfaces CORBA} is not defined, so I assume it is COM, or?
Title: Re: TFPGMap issue after upgrade to FPC 3.2.0
Post by: ASerge 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.
Title: Re: TFPGMap issue after upgrade to FPC 3.2.0
Post by: engkin 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.
Title: Re: TFPGMap issue after upgrade to FPC 3.2.0
Post by: antispam88 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
Title: Re: TFPGMap issue after upgrade to FPC 3.2.0
Post by: engkin 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.
Title: Re: TFPGMap issue after upgrade to FPC 3.2.0
Post by: engkin on April 23, 2021, 09:28:23 am
Please test the attached file
Title: Re: TFPGMap issue after upgrade to FPC 3.2.0
Post by: antispam88 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
Title: Re: TFPGMap issue after upgrade to FPC 3.2.0
Post by: antispam88 on May 05, 2021, 07:56:05 am
@engkin
Do you have any updates on the Free method?

Best regards,
antispam88
Title: Re: TFPGMap issue after upgrade to FPC 3.2.0
Post by: antispam88 on May 14, 2021, 07:51:07 am
Are there any news regarding my problem?
TinyPortal © 2005-2018