delphi - TJclStringList 在 Free 上崩溃

标签 delphi delphi-10.1-berlin jedi

创建一个简单的 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 单元提供了几个函数,可以为您正确创建接口(interface)实例。您可以在该单元中的 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.

关于delphi - TJclStringList 在 Free 上崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54533912/

相关文章:

sql - Delphi:访问 JSON 数组中的 JSON 对象

delphi - 使源代码可从 Delphi IDE 写入

delphi - 在注册表中将数据设置为子项时出错

sorting - 如何对字符串列表中的数字进行排序?

delphi - 点击通知后如何返回应用程序?

windows - 关于 JvPatchFile 组件?

python - jedi-vim 没有找到 python2 dist-packages,但是 python3 是的

windows - 如何在 Windows 7 Aero 任务预览中创建自己的控件?

delphi - 如何从 Delphi 10.1 Berlin 中的类助手访问私有(private)字段?

delphi - 编译完包后在哪里可以找到 bpl 文件?