TJclStringList 在免费时崩溃
TJclStringList crashes on Free
创建一个简单的 VCL 应用程序:
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
type
TForm1 = class(TForm)
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
JclStringLists;
var
MyList1: TJclStringList;
MyList2: TJclStringList;
procedure TForm1.FormDestroy(Sender: TObject);
begin
MyList1.Free;
MyList2.Free;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
MyList1 := TJclStringList.Create;
MyList2 := TJclStringList.Create;
MyList1.LoadFromFile('C:\ONE.txt');
MyList2.LoadFromFile('C:\TWO.txt');
Self.Caption := Self.Caption + ' ' + IntToStr(MyList1.Count);
Self.Caption := Self.Caption + ' ' + IntToStr(MyList2.Count);
end;
end.
尝试释放 MyList1 对象实例时,它在 TForm1.FormDestroy
事件处理程序中崩溃。为什么?
TJclStringList
是引用计数类型(它在 JCLStringLists.pas
中声明为 type TJclStringList = class(TJclInterfacedStringList, IInterface, IJclStringList)
并同时实现 _AddRef
和 _Release
来处理引用计数),所以你根本不应该将它们创建为对象,也不应该手动释放它们——当对它们的引用超出范围时,它们将自动释放。 (这也意味着你不应该将它们声明为全局变量,因为这样你就无法控制它们的生命周期。)
JclStringLists
单元提供了几个函数,可以正确地为您创建接口实例。您可以在该单元中看到它们,就在 implementation
关键字上方:
function JclStringList: IJclStringList; overload;
function JclStringListStrings(AStrings: TStrings): IJclStringList; overload;
function JclStringListStrings(const A: array of string): IJclStringList; overload;
function JclStringList(const A: array of const): IJclStringList; overload;
function JclStringList(const AText: string): IJclStringList; overload;
使用 TJclStringList
做你想做的事情的正确方法是这样的:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, JCLStringLists;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
MyList1, MyList2: IJCLStringList; // Note I and not T in type.
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
MyList1 := JclStringList;
MyList1.LoadFromFile('C:\Work\Data\FirstName.txt');
MyList2 := JclStringList
MyList2.LoadFromFile('C:\Work\Data\LastName.txt');
// Only to demonstrate that both files got loaded by the code above.
Self.Caption := Format('First: %d Last: %d', [MyList1.Count, MyList2.Count]);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
// Do NOT free the JclStringLists here - they will automatically be released when
// the form is destroyed because the reference count will reach zero (as long as
// you don't have any other references to those variables, which by putting them into
// the private section is unlikely.
end;
end.
创建一个简单的 VCL 应用程序:
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
type
TForm1 = class(TForm)
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
JclStringLists;
var
MyList1: TJclStringList;
MyList2: TJclStringList;
procedure TForm1.FormDestroy(Sender: TObject);
begin
MyList1.Free;
MyList2.Free;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
MyList1 := TJclStringList.Create;
MyList2 := TJclStringList.Create;
MyList1.LoadFromFile('C:\ONE.txt');
MyList2.LoadFromFile('C:\TWO.txt');
Self.Caption := Self.Caption + ' ' + IntToStr(MyList1.Count);
Self.Caption := Self.Caption + ' ' + IntToStr(MyList2.Count);
end;
end.
尝试释放 MyList1 对象实例时,它在 TForm1.FormDestroy
事件处理程序中崩溃。为什么?
TJclStringList
是引用计数类型(它在 JCLStringLists.pas
中声明为 type TJclStringList = class(TJclInterfacedStringList, IInterface, IJclStringList)
并同时实现 _AddRef
和 _Release
来处理引用计数),所以你根本不应该将它们创建为对象,也不应该手动释放它们——当对它们的引用超出范围时,它们将自动释放。 (这也意味着你不应该将它们声明为全局变量,因为这样你就无法控制它们的生命周期。)
JclStringLists
单元提供了几个函数,可以正确地为您创建接口实例。您可以在该单元中看到它们,就在 implementation
关键字上方:
function JclStringList: IJclStringList; overload;
function JclStringListStrings(AStrings: TStrings): IJclStringList; overload;
function JclStringListStrings(const A: array of string): IJclStringList; overload;
function JclStringList(const A: array of const): IJclStringList; overload;
function JclStringList(const AText: string): IJclStringList; overload;
使用 TJclStringList
做你想做的事情的正确方法是这样的:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, JCLStringLists;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
MyList1, MyList2: IJCLStringList; // Note I and not T in type.
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
MyList1 := JclStringList;
MyList1.LoadFromFile('C:\Work\Data\FirstName.txt');
MyList2 := JclStringList
MyList2.LoadFromFile('C:\Work\Data\LastName.txt');
// Only to demonstrate that both files got loaded by the code above.
Self.Caption := Format('First: %d Last: %d', [MyList1.Count, MyList2.Count]);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
// Do NOT free the JclStringLists here - they will automatically be released when
// the form is destroyed because the reference count will reach zero (as long as
// you don't have any other references to those variables, which by putting them into
// the private section is unlikely.
end;
end.