I found two cases that made me curious.
The first is why no memory leak occurs when using the JSON library.
If GetValue returns a TJSONValue that does not implement an interface. Why does my "if" not raise a memory leak?
procedure TFrmApp.btnJSONClick(Sender: TObject);
var
JSONObject: TJSONObject;
JSONStr: string;
begin
JSONStr := '{"colors":[{"name":"red", "hex":"#f00"}]}';
JSONObject := TJSONObject.ParseJSONValue(JSONStr) as TJSONObject;
try
// If GetValue returns a TJSONValue that does not implement an interface.
// Why does my "if" not raise a memory leak?
if JSONObject.GetValue('colors') <> nil then
memo.Lines.Add('Colors exist.')
else
memo.Lines.Add('Colors not found.');
finally
JSONObject.Free;
end;
end;
The second is why access violation does not occur when accessing the fields of the Cds.
If the Cds that provided the Data has been released from memory. Why does not access violation occur?
procedure TFrmApp.btnDataSetClick(Sender: TObject);
var
Cds: TClientDataSet;
begin
Cds := TClientDataSet.Create(Self);
try
Cds.Data := Self.GetData;
// If the Cds that provided the Data has been released from memory.
// Why does not access violation occur?
memo.Lines.Add('Name: ' + Cds.FieldByName('VendorName').AsString);
memo.Lines.Add('City: ' + Cds.FieldByName('City').AsString);
finally
Cds.Free;
end;
end;
function TFrmApp.GetData: OleVariant;
var
Cds: TClientDataSet;
begin
Cds := TClientDataSet.Create(Self);
try
Cds.LoadFromFile(TDirectory.GetCurrentDirectory + '\data.xml');
Result := Cds.Data;
finally
Cds.Free;
end;
end;
Sample Project:
.DPR
program TestMemoryLeak;
uses
Vcl.Forms,
uApp in 'uApp.pas' {FrmApp};
{$R *.res}
begin
ReportMemoryLeaksOnShutdown := true;
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TFrmApp, FrmApp);
Application.Run;
end.
uAPP.pas
unit uApp;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.JSON, REST.Json, Datasnap.DBClient, Data.DB,
System.IOUtils;
type
TFrmApp = class(TForm)
btnJSON: TButton;
btnDataSet: TButton;
memo: TMemo;
procedure btnJSONClick(Sender: TObject);
procedure btnDataSetClick(Sender: TObject);
private
{ Private declarations }
function GetData: OleVariant;
public
{ Public declarations }
end;
var
FrmApp: TFrmApp;
implementation
{$R *.dfm}
procedure TFrmApp.btnJSONClick(Sender: TObject);
var
JSONObject: TJSONObject;
JSONStr: string;
begin
JSONStr := '{"colors":[{"name":"red", "hex":"#f00"}]}';
JSONObject := TJSONObject.ParseJSONValue(JSONStr) as TJSONObject;
try
// If GetValue returns a TJSONValue that does not implement an interface.
// Why does my "if" not raise a memory leak?
if JSONObject.GetValue('colors') <> nil then
memo.Lines.Add('Colors exist.')
else
memo.Lines.Add('Colors not found.');
finally
JSONObject.Free;
end;
end;
procedure TFrmApp.btnDataSetClick(Sender: TObject);
var
Cds: TClientDataSet;
begin
Cds := TClientDataSet.Create(Self);
try
Cds.Data := Self.GetData;
// If the Cds that provided the Data has been released from memory.
// Why does not access violation occur?
memo.Lines.Add('Name: ' + Cds.FieldByName('VendorName').AsString);
memo.Lines.Add('City: ' + Cds.FieldByName('City').AsString);
finally
Cds.Free;
end;
end;
function TFrmApp.GetData: OleVariant;
var
Cds: TClientDataSet;
begin
Cds := TClientDataSet.Create(Self);
try
Cds.LoadFromFile(TDirectory.GetCurrentDirectory + '\data.xml');
Result := Cds.Data;
finally
Cds.Free;
end;
end;
end.
uApp.dfm
object FrmApp: TFrmApp
Left = 0
Top = 0
Caption = 'FrmApp'
ClientHeight = 245
ClientWidth = 516
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
Position = poScreenCenter
PixelsPerInch = 96
TextHeight = 13
object btnJSON: TButton
Left = 24
Top = 30
Width = 75
Height = 25
Caption = 'JSON'
TabOrder = 0
OnClick = btnJSONClick
end
object btnDataSet: TButton
Left = 24
Top = 96
Width = 75
Height = 25
Caption = 'DataSet'
TabOrder = 1
OnClick = btnDataSetClick
end
object memo: TMemo
Left = 176
Top = 8
Width = 321
Height = 229
TabOrder = 2
end
end
data.xml
<?xml version="1.0" standalone="yes"?>
<DATAPACKET Version="2.0">
<METADATA>
<FIELDS>
<FIELD attrname="VendorNo" fieldtype="r8"/>
<FIELD attrname="VendorName" fieldtype="string" WIDTH="30"/>
<FIELD attrname="City" fieldtype="string" WIDTH="20"/>
<FIELD attrname="State" fieldtype="string" WIDTH="20"/>
</FIELDS>
<PARAMS DEFAULT_ORDER="1" PRIMARY_KEY="1" LCID="1033"/>
</METADATA>
<ROWDATA>
<ROW VendorNo="2014" VendorName="Cacor Corporation" City="Southfield" State="OH"/>
<ROW VendorNo="2641" VendorName="Underwater" City="Indianapolis" State="IN" />
<ROW VendorNo="2674" VendorName="J.W. Luscher Mfg." City="Berkely" State="MA"/>
<ROW VendorNo="3511" VendorName="Scuba Professionals" City="Rancho Dominguez"/>
<ROW VendorNo="3819" VendorName="Divers' Supply Shop" City="Macon" State="GA"/>
</ROWDATA>
</DATAPACKET>
why no memory leak occurs when using the JSON library.
If GetValue returns a TJSONValue that does not implement an interface. Why does my "if" not raise a memory leak?
TJSONObject.GetValue()
returns a pointer to a TJSONValue
object that is owned internally by the TJSONObject
. The TJSONValue
will be freed when the TJSONObject
is freed, which you do at the end of your procedure. GetValue()
does not allocate any new memory for output, so there is nothing for you to free, hence no leak.
why access violation does not occur when accessing the fields of the Cds.
If the Cds that provided the Data has been released from memory. Why does not access violation occur?
You are assigning the source ClientDataSet's Data
property to an OleVariant
, and then assigning that to the other ClientDataSet's Data
property. OleVariant
makes a copy of whatever data is assigned to it (and in the case of [arrays of] interfaced objects, it increments their reference counts), so whether the original ClientDataSet is freed or not makes no difference because the OleVariant
is independent and manages the data it is holding.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.