Json parser call twice to destroy on Delphi linux

bug

(DonaldShimoda) #1

RO version stable

Call destroy, destroy calls clear, clear call destroy…

39


(DonaldShimoda) #2

To be clear, in DELPHI RIO 10.3 I have that kind of objects.

var
  soJsonData        : TROJSONValue;
  soJsonPackage     : TROJSONObject;
  apk_fields        : TROJSONArray;
  apk_field_item    : TROJSONObject;
  apk_field_list    : TArrayofFields;
  arows             : TROJSONArray;
  a_fields_def      : TROJSONArray;
  a_field_def_item  : TROJSONObject;
  arow              : TROJSONObject;
  afields           : TROJSONArray;
  afield            : TROJSONObject;

Wich is the right way to free that objects?

FreeandNil Fails.

Another question related:

Why are you calling disposeof on Delphi for linux compiler and not plain free?

procedure FreeOrDisposeOfAndNil(var Obj);
begin
  FreeOrDisposeOf(TObject(Obj));
  TObject(Obj) := nil;
end;

and then

procedure FreeOrDisposeOf(anObject: TObject);
begin
  {$IFDEF DELPHIXE4UP}
  anObject.DisposeOf;
  {$ELSE}
  anObject.Free;
  {$ENDIF}
end;

I believe that code is wrong for linux Delphi compiler (not using ARC anymore on RIO version)

Im wrong?

Best regards


(EvgenyK) #3

can you show callstack for it, pls?

as for me - everything is correct.

destructor TROJSONValue.Destroy;
begin
  Clear;  //<<< clears FObject
  inherited; //<<< calls ancestor destroy, i.e. TCollectionItem.Destroy
end;

if I understand correctly, you have soJsonData on the top and all others your objects are nested into soJsonData, so you should destroy only soJsonData.


if you see at implementation of TObject.DisposeOf, you will see code like

procedure TObject.DisposeOf;
begin
{$IFDEF AUTOREFCOUNT}
...
{$ELSE}
  Free;
{$ENDIF}
end;

so it just calls Free;


(DonaldShimoda) #4

Ok, will try only releasing that object


(DonaldShimoda) #6

This is the exact point where the Segmentation fault happens. Can´t find the reasons. Have any idea things to check?

Note. I change the code to see if the exception raises on the freeordisposeandnil call.


(EvgenyK) #7

can you create a simple testcase that reproduces this issue, pls?


(DonaldShimoda) #8

Very hard to do because have a lot of preprocessing not related…

I remove all the freenandil and let only the FreeandNil for soJsonData and now the segmentation fault bit the memory leaks return…

Question, I work this way:

soJsonPackage     := soJsonData.AsObject;

apk_fields := soJsonPackage.FindItem('pk_fields').ASArray;

and then work with apk_fields.

None of that variables need to be free? apk_fields in this case need to be free before reuse or dont?

  Freeandnil(apk_fields);
   
  apk_fields := soJsonPackage.FindItem('pk_fields').ASArray;

When I activate that FreeandNil before reuse the Segmentation fault on Freeandnil(soJsonData) returns…


(EvgenyK) #9

if you think, that some json objects aren’t destroyed correctly, you can add some extra code into all classes of uROJSONParser unit like

constructor TROJSONValue.Create(Collection: TCollection);
begin
   ROInterlockedIncrement(some_global_variable);
...
destructor TROJSONValue.Destroy;
begin
   ROInterlockedDecrement(some_global_variable);
...

and then check these variables after working with json objects


None of that variables have to be freed. only top level objects should be freed.
above code is similar to

fld := fields.FindField('fld1');
FreeAndNil(fld);
...
fields.Free;

if you want to clear some object, you can call Clear, like

  soJsonPackage.FindItem('pk_fields').Clear;

instead of

  apk_fields := soJsonPackage.FindItem('pk_fields').ASArray;
  Freeandnil(apk_fields);

(DonaldShimoda) #10

Thanks Evgeny! Just releasing the main object do the job. The memory problem I gone, the system seems to be very stable now. Will continue checking and let you know if something changes.

Best regards.