TList抛出异常

发布于 2025-01-14 10:48:38 字数 3607 浏览 0 评论 0原文

我有以下代码:

program Tlist;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  madExcept,
  madLinkDisAsm,
  madListHardware,
  madListProcesses,
  madListModules,
  System.Generics.Collections,
  System.SysUtils;

type
  TMyItem = class(TInterfacedObject)
  private
    ItemPrice: Currency;
  public
    constructor Create(const aItemPrice: Currency); reintroduce;
  end;

  IMyList = interface
    ['{1D11BD29-5C1E-4171-B67E-FB9157DCB021}']
    function Reset(const aItems: Integer): Integer;
    function Add(const aPrice, aItemN: Integer): Integer;
  end;

  TMyList = class(TInterfacedObject, IMyList)
  private
    FList: array of TList<TMyItem>;
  public
    function Reset(const aItems: Integer): Integer;
    function Add(const aPrice, aItemN: Integer): Integer;
  end;

{ TMyList }

function TMyList.Add(const aPrice, aItemN: Integer): Integer;
begin
  FList[aItemN].Add(TMyItem.Create(aPrice));
  Result := FList[aItemN].Count;
end;

function TMyList.Reset(const aItems: Integer): Integer;
var
  I: Integer;
begin
  SetLength(FList, 0);
  SetLength(FList, aItems);
  for I := 0 to Length(FList) - 1 do
  begin
    FList[I] := TList<TMyItem>.Create;
  end;
  Result := Length(FList);
end;

{ TMyItem }

constructor TMyItem.Create(const aItemPrice: Currency);
begin
  ItemPrice := aItemPrice;
end;

var
  MyList: IMyList;

begin
  MyList := TMyList.Create;
  MyList.Reset(3);
  mylist.Add(1000, 1);
end.

执行时,它会抛出链接到 TList 的异常。

由于 TList 实现了引用计数,并且所有类均派生自 TInterfacedObject 我的印象是内存会自动释放,但显然,我错了。

我做错了什么?

编辑

根据建议,我想出了以下代码:

program Tlist2;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  madExcept,
  madLinkDisAsm,
  madListHardware,
  madListProcesses,
  madListModules,
  System.Generics.Collections,
  System.SysUtils;

type
  IMyItem = interface
    ['{2EB53CC3-E5FC-474B-A162-30BBD2D17C48}']
  end;

  TMyItem = class(TInterfacedObject, IMyItem )
  private
    ItemPrice: Currency;
  public
    constructor Create(const aItemPrice: Currency); reintroduce;
  end;

  IMyList = interface
    ['{1D11BD29-5C1E-4171-B67E-FB9157DCB021}']
    function Reset(const aItems: Integer): Integer;
    function Add(const aPrice, aItemN: Integer): Integer;
  end;

  TMyList = class(TInterfacedObject, IMyList)
  private
    FList: array of TList<TMyItem>;
  public
    function Reset(const aItems: Integer): Integer;
    function Add(const aPrice, aItemN: Integer): Integer;
    destructor Destroy; override;
  end;

{ TMyList }

function TMyList.Add(const aPrice, aItemN: Integer): Integer;
begin
  FList[aItemN].Add(TMyItem.Create(aPrice));
  Result := FList[aItemN].Count;
end;

destructor TMyList.Destroy;
var
  I: Integer;
  a: Integer;
begin
  for I := 0 to Length(FList) - 1 do
  begin
    if FList[I].Count > 0 then
    begin
      for a := 0 to FList[I].Count - 1 do
      begin
        FList[I][a].Destroy
      end;
    end;
    FList[I].Destroy;
  end;
  inherited;
end;

function TMyList.Reset(const aItems: Integer): Integer;
var
  I: Integer;
begin
  SetLength(FList, 0);
  SetLength(FList, aItems);
  for I := 0 to Length(FList) - 1 do
  begin
    FList[I] := TList<TMyItem>.Create;
  end;
  Result := Length(FList);
end;

{ TMyItem }

constructor TMyItem.Create(const aItemPrice: Currency);
begin
  ItemPrice := aItemPrice;
end;

var
  MyList: IMyList;


begin
  MyList := TMyList.Create;
  MyList.Reset(3);
  mylist.Add(1000, 1);
end.

工作正常,不再有内存泄漏,但我觉得我在这里错过了一些东西。 我认为通过使用接口并从 TInterfacedObject 派生我的类,销毁器就不是必需的了。

I have the following code:

program Tlist;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  madExcept,
  madLinkDisAsm,
  madListHardware,
  madListProcesses,
  madListModules,
  System.Generics.Collections,
  System.SysUtils;

type
  TMyItem = class(TInterfacedObject)
  private
    ItemPrice: Currency;
  public
    constructor Create(const aItemPrice: Currency); reintroduce;
  end;

  IMyList = interface
    ['{1D11BD29-5C1E-4171-B67E-FB9157DCB021}']
    function Reset(const aItems: Integer): Integer;
    function Add(const aPrice, aItemN: Integer): Integer;
  end;

  TMyList = class(TInterfacedObject, IMyList)
  private
    FList: array of TList<TMyItem>;
  public
    function Reset(const aItems: Integer): Integer;
    function Add(const aPrice, aItemN: Integer): Integer;
  end;

{ TMyList }

function TMyList.Add(const aPrice, aItemN: Integer): Integer;
begin
  FList[aItemN].Add(TMyItem.Create(aPrice));
  Result := FList[aItemN].Count;
end;

function TMyList.Reset(const aItems: Integer): Integer;
var
  I: Integer;
begin
  SetLength(FList, 0);
  SetLength(FList, aItems);
  for I := 0 to Length(FList) - 1 do
  begin
    FList[I] := TList<TMyItem>.Create;
  end;
  Result := Length(FList);
end;

{ TMyItem }

constructor TMyItem.Create(const aItemPrice: Currency);
begin
  ItemPrice := aItemPrice;
end;

var
  MyList: IMyList;

begin
  MyList := TMyList.Create;
  MyList.Reset(3);
  mylist.Add(1000, 1);
end.

When executed, it throws an exception linked to TList<T>.

As TList implements the reference counting and all the classes are derived from TInterfacedObject I was under the impression that the memory would be released automatically but obviously, I am wrong.

What am I doing wrong?

EDIT

Following the suggestions I came up with the following code:

program Tlist2;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  madExcept,
  madLinkDisAsm,
  madListHardware,
  madListProcesses,
  madListModules,
  System.Generics.Collections,
  System.SysUtils;

type
  IMyItem = interface
    ['{2EB53CC3-E5FC-474B-A162-30BBD2D17C48}']
  end;

  TMyItem = class(TInterfacedObject, IMyItem )
  private
    ItemPrice: Currency;
  public
    constructor Create(const aItemPrice: Currency); reintroduce;
  end;

  IMyList = interface
    ['{1D11BD29-5C1E-4171-B67E-FB9157DCB021}']
    function Reset(const aItems: Integer): Integer;
    function Add(const aPrice, aItemN: Integer): Integer;
  end;

  TMyList = class(TInterfacedObject, IMyList)
  private
    FList: array of TList<TMyItem>;
  public
    function Reset(const aItems: Integer): Integer;
    function Add(const aPrice, aItemN: Integer): Integer;
    destructor Destroy; override;
  end;

{ TMyList }

function TMyList.Add(const aPrice, aItemN: Integer): Integer;
begin
  FList[aItemN].Add(TMyItem.Create(aPrice));
  Result := FList[aItemN].Count;
end;

destructor TMyList.Destroy;
var
  I: Integer;
  a: Integer;
begin
  for I := 0 to Length(FList) - 1 do
  begin
    if FList[I].Count > 0 then
    begin
      for a := 0 to FList[I].Count - 1 do
      begin
        FList[I][a].Destroy
      end;
    end;
    FList[I].Destroy;
  end;
  inherited;
end;

function TMyList.Reset(const aItems: Integer): Integer;
var
  I: Integer;
begin
  SetLength(FList, 0);
  SetLength(FList, aItems);
  for I := 0 to Length(FList) - 1 do
  begin
    FList[I] := TList<TMyItem>.Create;
  end;
  Result := Length(FList);
end;

{ TMyItem }

constructor TMyItem.Create(const aItemPrice: Currency);
begin
  ItemPrice := aItemPrice;
end;

var
  MyList: IMyList;


begin
  MyList := TMyList.Create;
  MyList.Reset(3);
  mylist.Add(1000, 1);
end.

That works fine, no more memory leaks BUT I am under the impression that I am missing out on something here.
I thought that by using interfaces and deriving my classes from TInterfacedObject the destroyer would not be necessary.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

热风软妹 2025-01-21 10:48:38

根据 David 和 Remi 的意见,我修改了我的代码:

program Tlist3;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  madExcept,
  madLinkDisAsm,
  madListHardware,
  madListProcesses,
  madListModules,
  System.Generics.Collections,
  System.SysUtils;

type
  IMyItem = interface
    ['{2EB53CC3-E5FC-474B-A162-30BBD2D17C48}']
  end;

  TMyItem = class(TInterfacedObject)
  private
    ItemPrice: Currency;
  public
    constructor Create(const aItemPrice: Currency); reintroduce;
  end;

  IMyList = interface
    ['{1D11BD29-5C1E-4171-B67E-FB9157DCB021}']
    function Reset(const aItems: Integer): Integer;
    function Add(const aPrice, aItemN: Integer): Integer;
  end;

  TMyList = class(TInterfacedObject, IMyList)
  private
    FList: array of TObjectList<TMyItem>;
  public
    function Reset(const aItems: Integer): Integer;
    function Add(const aPrice, aItemN: Integer): Integer;
    destructor Destroy; override;
  end;

{ TMyList }

function TMyList.Add(const aPrice, aItemN: Integer): Integer;
begin
  FList[aItemN].Add(TMyItem.Create(aPrice));
  Result := FList[aItemN].Count;
end;

destructor TMyList.Destroy;
var
  I: Integer;
  a: Integer;
begin
  if Length(FList) > 0 then
  begin
    for I := 0 to Length(FList) - 1 do
    begin
      FList[I].Free;
    end;
  end;
  inherited;
end;

function TMyList.Reset(const aItems: Integer): Integer;
var
  I: Integer;
begin
  if Length(FList) > 0 then
  begin
    for I := 0 to Length(FList) - 1 do
    begin
      FList[I].Free;
    end;
  end;
  SetLength(FList, 0);
  SetLength(FList, aItems);
  for I := 0 to Length(FList) - 1 do
  begin
    FList[I] := TObjectList<TMyItem>.Create;
  end;
  Result := Length(FList);
end;

{ TMyItem }

constructor TMyItem.Create(const aItemPrice: Currency);
begin
  ItemPrice := aItemPrice;
end;

var
  MyList: IMyList;


begin
  MyList := TMyList.Create;
  MyList.Reset(3);
  mylist.Add(1000, 1);
  mylist.Add(2000, 2);
  MyList.Reset(2);
  mylist.Add(1000, 0);
  mylist.Add(2000, 1);
end.

没有内存泄漏。

Following the input from David and Remi I have amended my code:

program Tlist3;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  madExcept,
  madLinkDisAsm,
  madListHardware,
  madListProcesses,
  madListModules,
  System.Generics.Collections,
  System.SysUtils;

type
  IMyItem = interface
    ['{2EB53CC3-E5FC-474B-A162-30BBD2D17C48}']
  end;

  TMyItem = class(TInterfacedObject)
  private
    ItemPrice: Currency;
  public
    constructor Create(const aItemPrice: Currency); reintroduce;
  end;

  IMyList = interface
    ['{1D11BD29-5C1E-4171-B67E-FB9157DCB021}']
    function Reset(const aItems: Integer): Integer;
    function Add(const aPrice, aItemN: Integer): Integer;
  end;

  TMyList = class(TInterfacedObject, IMyList)
  private
    FList: array of TObjectList<TMyItem>;
  public
    function Reset(const aItems: Integer): Integer;
    function Add(const aPrice, aItemN: Integer): Integer;
    destructor Destroy; override;
  end;

{ TMyList }

function TMyList.Add(const aPrice, aItemN: Integer): Integer;
begin
  FList[aItemN].Add(TMyItem.Create(aPrice));
  Result := FList[aItemN].Count;
end;

destructor TMyList.Destroy;
var
  I: Integer;
  a: Integer;
begin
  if Length(FList) > 0 then
  begin
    for I := 0 to Length(FList) - 1 do
    begin
      FList[I].Free;
    end;
  end;
  inherited;
end;

function TMyList.Reset(const aItems: Integer): Integer;
var
  I: Integer;
begin
  if Length(FList) > 0 then
  begin
    for I := 0 to Length(FList) - 1 do
    begin
      FList[I].Free;
    end;
  end;
  SetLength(FList, 0);
  SetLength(FList, aItems);
  for I := 0 to Length(FList) - 1 do
  begin
    FList[I] := TObjectList<TMyItem>.Create;
  end;
  Result := Length(FList);
end;

{ TMyItem }

constructor TMyItem.Create(const aItemPrice: Currency);
begin
  ItemPrice := aItemPrice;
end;

var
  MyList: IMyList;


begin
  MyList := TMyList.Create;
  MyList.Reset(3);
  mylist.Add(1000, 1);
  mylist.Add(2000, 2);
  MyList.Reset(2);
  mylist.Add(1000, 0);
  mylist.Add(2000, 1);
end.

No memory leaks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文