TJclStringList вылетает на Free - PullRequest
       74

TJclStringList вылетает на Free

0 голосов
/ 05 февраля 2019

Создайте простое приложение 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.

Сбой в обработчике событий TForm1.FormDestroy при попытке освободить экземпляр объекта MyList1 .Почему?

1 Ответ

0 голосов
/ 05 февраля 2019

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.
...