Tuesday, 25 April 2023
  6 Replies
  1.5K Visits
  Subscribe
Hello,

we identified that the generated code of your OpenAPI generator has no handling for freeing sub objects.

Example:

TsgcOpenAPI_ListOrganizationsResponse_Class = class(TsgcOpenAPIClass)
private
  Fdata: TArray<TsgcOpenAPI_OrganizationResponse_Class>; // <-- No release of this objects!
  Fcount: integer;
  F_type: String;
public
  class function Read(const aValue: string): TsgcOpenAPI_ListOrganizationsResponse_Class;
public
  property Data: TArray<TsgcOpenAPI_OrganizationResponse_Class> read Fdata write Fdata;
  property Count: integer read Fcount write Fcount;
  property _type: String read F_type write F_type;
end;


In this example the items of the array Data was not released, when the TsgcOpenAPI_ListOrganizationsResponse_Class instance get freed.

The generator should dynamically generate a destructor with special handling for such cases.

Best regards,
Waldemar Derr
2 years ago
·
#1565
Hello,

Yes, it's a known bug, it will be fixed on the next release. Thanks for the feedback.

Kind Regards,
Sergio
2 years ago
·
#1566
Hi Sergio,

until you are ready we use this workaround:


uses

  System.Rtti,
  System.SysUtils,
  System.TypInfo,

  sgcHTTP_OpenAPI_Client;

procedure sgcReleaseMembers(const AObject: TsgcOpenAPIClass);

implementation

var
  Ctx: TRttiContext;

procedure sgcReleaseMembers(const AObject: TsgcOpenAPIClass);
type
  TObjectArray = TArray<TObject>;
  PObjectArray = ^TObjectArray;
var
  LType: TRttiType;
  LProp: TRttiProperty;
begin
  LType:=Ctx.GetType(AObject.ClassType);
  for LProp in LType.GetProperties do
  begin
    case LProp.PropertyType.TypeKind of
      tkClass:
      begin
        if not LProp.IsWritable then Continue;

        var PropValue:=LProp.GetValue(AObject);
        var PropObj:=PropValue.AsObject;

        if Assigned(PropObj) then
        begin
          if PropObj is TsgcOpenAPIClass
            then sgcReleaseMembers(TsgcOpenAPIClass(PropObj));
          PropObj.Free;
          LProp.SetValue(AObject,nil);
        end;
      end;
      tkDynArray:
      begin
        var CheckType:=Ctx.GetType(LProp.PropertyType.Handle);
        if CheckType is TRttiDynamicArrayType then
        begin
          var ArrType:=TRttiDynamicArrayType(CheckType);
          if ArrType.ElementType.TypeKind = tkClass then
          begin
            var ArrProperty:=LProp.GetValue(AObject);
            var ObjArray:=PObjectArray(ArrProperty.GetReferenceToRawData);
            if not Assigned(ObjArray) then Continue;

            for var cc := 0 to Length(ObjArray^) - 1 do
            begin
              if Assigned(ObjArray^[cc]) and (ObjArray^[cc] is TsgcOpenAPIClass)
                then sgcReleaseMembers(TsgcOpenAPIClass(ObjArray^[cc]));
              ObjArray^[cc].Free;
              ObjArray^[cc]:=nil;
            end;
          end;
        end;
      end;
    end;
  end;
end;

initialization
  Ctx := TRttiContext.Create;

end.


Before a Instance.Free, we call sgcReleaseMembers(Instance).
You can use it for your solution, completely or partially.
2 years ago
·
#1567
Hi,

Thanks for the code!! I really appreciate it.

Kind Regards,
Sergio
2 years ago
·
#1570
Hello,

I've released a new version which includes your fix, thanks for the feedback.

Kind Regards,
Sergio
2 years ago
·
#1583
Hi Sergio,

I can confirm, that the memory leaks are gone in the 2023.4.0 release.

Best regards,
Waldemar
2 years ago
·
#1585
Hi,

Thanks for letting me know.

Kind Regards,
Sergio
  • Page :
  • 1
There are no replies made for this post yet.
Submit Your Response
Upload files or images for this discussion by clicking on the upload button below.
Supported: gif,jpg,png,jpeg,zip,rar,pdf,pas,dfm,dpr,dproj,dpk
· Insert · Remove
  Upload Files (Maximum 10MB)