Delphi 将我的对象编组为字符串泄漏,但为什么呢?

Delphi Marshalling my object to string leaks, but why?

我想知道为什么将我的对象编组为字符串会泄漏,我已尝试释放 JSONMarshal(实际上还试图通过实例化它来释放转换器)- 但它仍然泄漏?释放 JSONMarshal 还不够吗?

function TPerson.ToJsonString: string;
var
  JSONMarshal: TJSONMarshal;
begin
  result := '';
  JSONMarshal := TJSONMarshal.Create(TJSONConverter.Create);
  try
    Result := JSONMarshal.Marshal(self).ToString;
  finally
    JSONMarshal.Free;
  end;
end;

这是一个测试对象 - 只需创建 TPerson (1, ') 的实例并调用 ToJsonString - 然后你就会看到泄漏。

unit TestObjU;

interface

uses
  Classes, System.Generics.Collections, System.SysUtils,
  Data.DBXJSON, Data.DBXJSONReflect, JSON,
  Data.FireDACJSONReflect, FireDAC.Comp.Client, vcl.ExtCtrls,
  pngimage, graphics, variants;

type
  EPerson = class(Exception);
  EPersonsList = class(Exception);

  TGender = (Female, Male);

  TPerson = class(TObject)
  private
    FFirstName: string;
    FLastName: string;
    FId: Integer;
    FGender: TGender;
    FModified : Boolean;
    [JSONMarshalled(False)]
    FPicture : TPicture;
    function GetName: string;
    procedure SetFirstName(const Value: string);
    procedure SetLastName(const Value: string);
    function GetId: Integer;
    procedure SetGender(const Value: TGender);
    procedure SetModified(const Value: Boolean);


  public
    property Id : Integer read GetId;
    property Name : string read GetName;
    property FirstName : string read FFirstName write SetFirstName;
    property LastName : string read FLastName write SetLastName;
    property Gender : TGender read FGender write SetGender;
    property Modified : Boolean read FModified write SetModified;
    [JSONMarshalled(False)]
    property Picture : TPicture read FPicture write FPicture;
    function Update : Boolean;
    function Delete : Boolean;

    constructor Create(AId : Integer; AFirstName, ALastName : string; AGender : TGender); overload;
    destructor destroy; override;

    function ToJsonString: string;
    class function FromJsonString(AJSONString: string): TPerson; static;

  end;

implementation

{ TPerson }

constructor TPerson.Create(AId: Integer; AFirstName, ALastName: string;
  AGender: TGender);
begin
  inherited Create;
  FPicture := TPicture.Create;
  FId := AId;
  FFirstName := AFirstName;
  FLastName := ALastName;
  FGender := AGender;
end;

function TPerson.Delete: Boolean;
begin
  Result := False;
  if (FId > 0) then // if Id below zero we have a problem
  begin
    Result := True;
    FModified := False;
  end;
end;

destructor TPerson.destroy;
begin
  FreeAndNil(FPicture);
  inherited;
end;

function TPerson.GetId: Integer;
begin
  Result := FId;
end;

function TPerson.GetName: string;
begin
  Result := FFirstName + ' ' + FLastName;
end;

procedure TPerson.SetFirstName(const Value: string);
begin
  FFirstName := Value;
  FModified := True;
end;

procedure TPerson.SetGender(const Value: TGender);
begin
  FGender := Value;
  FModified := True;
end;

procedure TPerson.SetLastName(const Value: string);
begin
  FLastName := Value;
  FModified := True;
end;

procedure TPerson.SetModified(const Value: Boolean);
begin
  FModified := Value;
end;

function TPerson.ToJsonString: string;
var
  JSONMarshal: TJSONMarshal;
begin
  result := '';
  JSONMarshal := TJSONMarshal.Create(TJSONConverter.Create, True);
  try
    Result := JSONMarshal.Marshal(self).ToString;
  finally
    JSONMarshal.Free;
  end;
end;

class function TPerson.FromJsonString(AJSONString: string): TPerson;
var
  JSONUnMarshal: TJSONUnMarshal;
begin
  JSONUnMarshal := TJSONUnMarshal.Create;
  try
    Result := JSONUnMarshal.Unmarshal(TJSONObject.ParseJSONValue(AJSONString)) as TPerson;
  finally
    JSONUnMarshal.Free;
  end;
end;

function TPerson.Update: Boolean;
var
  AStream : TMemoryStream;
begin
  if (FId > 0) then // if Id below zero we have a problem
  begin
    AStream := TMemoryStream.Create;
    try
      Picture.Graphic.SaveToStream(AStream);
      AStream.Position := 0; // wind back if needed
    finally
      FreeAndNil(AStream);
    end;
  end;
  FModified := False;
end;

{ TPersonsList<T> }


end.



procedure TForm2.Button1Click(Sender: TObject);
var
  APerson : TPerson;
begin

  APerson := TPerson.Create(1, 'Donald', 'Duck', Male);
  try

    Memo1.Lines.Add(APerson.ToJsonString);

  finally
    APerson.Free;
  end;
end;

编组 returns 一个 TJSONValue 实例,在我看来你需要销毁这个实例。

function TPerson.ToJsonString: string;
var
  JSONMarshal: TJSONMarshal;
  Value: TJSONValue;
begin
  JSONMarshal := TJSONMarshal.Create(TJSONConverter.Create, True);
  try
    Value := JSONMarshal.Marshal(Self);
    try
      Result := Value.ToString;
    finally
      Value.Free;
    end;
  finally
    JSONMarshal.Free;
  end;
end;

你反方向操作的方法,同样的错误。应该是:

class function TPerson.FromJsonString(AJSONString: string): TPerson;
var
  JSONUnMarshal: TJSONUnMarshal;
  Value: TJSONValue;
begin
  JSONUnMarshal := TJSONUnMarshal.Create;
  try
    Value := TJSONObject.ParseJSONValue(AJSONString);
    try
      Result := JSONUnMarshal.Unmarshal(Value) as TPerson;
    finally
      Value.Free;
    end;
  finally
    JSONUnMarshal.Free;
  end;
end;