【问题标题】:Delphi: TList Creation, memory errorDelphi:TList 创建,内存错误
【发布时间】:2015-04-27 10:35:06
【问题描述】:

我尝试创建 3 个 TList,但是在创建它们时出现错误。

unit ipname;

interface

uses
  System.Generics.Collections;

type
  IpNameData = class
  private
    ips : TList<String>;
    ports : TList<integer>;
    names : TList<String>;
  public
    procedure Add(ip:string; port:integer; name:string);
    procedure Del(ip:string; port:integer; name:string);
    procedure Clear();
    function GetName(i:integer):string;
    function GetIp(i:integer):string;
    function GetPort(i:integer):integer;
    function GetSize(i:integer):integer;


  published
    constructor Create;
  end;
implementation

constructor IpNameData.Create;
begin
  ips := TList<String>.Create();
  ports := TList<integer>.Create();
  names := TList<String>.Create();
end;
...

所以问题发生在程序到达ips := TList&lt;String&gt;.Create(); 时,我得到:

First chance exception at $008BACCF. Exception class $C0000005 with message 'access violation at 0x008baccf: read of address 0x00000074'. Process Server.exe (5824)

我不知道我做错了什么:\

编辑

这对我来说有点乱……

但是我有 3 个文件,ipname 在上面,第二个是一个名为 ServerData 的 DataModule

unit ServerData;

interface

uses
   System.SysUtils, System.Classes, IdBaseComponent, IdComponent,
    IdCustomTCPServer, IdTCPServer, IdContext,FMX.Dialogs, ipname;
type
  TDataModule2 = class(TDataModule)
    TCPServer: TIdTCPServer;
    procedure TCPServerConnect(AContext: TIdContext);
    procedure TCPServerDisconnect(AContext: TIdContext);
    procedure TCPServerExecute(AContext: TIdContext);
  private
    { Private declarations }
     procedure CMDToDo(cmd,ip:string; p:integer);
  public
    { Public declarations }
    Logs:TStrings;
    IPs:TStrings;
    Data : IpNameData;
    procedure SendMSG(IP,msg : string; port : integer);
  end;

var
  DataModule2: TDataModule2;

最后一个是ServerGUI

unit ServerGUI;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Layouts,
  FMX.Memo, FMX.StdCtrls, FMX.Controls.Presentation, FMX.Edit, FMX.ListBox;

type
  TForm1 = class(TForm)
    Options: TGroupBox;
    Power: TSwitch;
    PortField: TEdit;
    Port_label: TLabel;
    Power_label: TLabel;
    LogM: TMemo;
    Logs: TGroupBox;
    IPBox: TListBox;
    IPBox_label: TLabel;
    LogM_label: TLabel;
    procedure PowerSwitch(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

uses ServerData;
procedure TForm1.FormCreate(Sender: TObject);
begin
   ServerData.DataModule2.Data.Create;
end;

我真的不知道应该在哪里调用构造函数,所以我在创建表单时调用...

【问题讨论】:

  • 真的用 () 调用 Create 吗?我已经多年没有编写 Delphi 代码了,但我想记住你只是调用 TList.Create;没有 ()。
  • 请显示调用 IpNameData 构造函数的代码。
  • @Nidhoegger 没关系。 () 可以包含或省略。
  • 您对问题的编辑证明我的猜测是正确的。您在问题中未能正确创建对象的代码与我的答案中的代码相同。
  • 至于如何创建Data,你是在错误的地方创建它。您需要在数据模块中处理Data 的生命周期的重写构造函数和析构函数。你不应该从外面这样做。

标签: delphi tlist


【解决方案1】:

问题中的代码很好。错误的代码是调用构造函数的代码。我敢打赌,上面写着:

var
  Data: IpNameData;
....
Data.Create;

应该写在哪里:

Data := IpNameData.Create;

【讨论】:

  • 即使在这种情况下它不是错误,我也会在 IpNameData 构造函数中调用 Inherited 以避免混淆。
  • @LURD 我同意。并覆盖Destroy 并销毁这三个列表。
【解决方案2】:

根据大卫的回复+ cmets,你应该替换

procedure TForm1.FormCreate(Sender: TObject);
begin
   ServerData.DataModule2.Data.Create;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
   ServerData.DataModule2.Data:=IpNameData.Create;
end;

更新

IpNameData = class
  private
    ips : TList<String>;
    ports : TList<integer>;
    names : TList<String>;

IpNameData = class
  private
    ips : TList<String>;
    ports : TList<integer>;
    names : TList<String>;
    destructor Destroy; override;

并添加

destructor IpNameData.Destroy;
begin
  ips.Free;
  ports.Free;
  Name.Free;
  inherited Destroy;
end;

改变

constructor IpNameData.Create;
begin
  ips := TList<String>.Create();
  ports := TList<integer>.Create();
  names := TList<String>.Create();
end;

constructor IpNameData.Create;
begin
  inherited Create;
  ips := TList<String>.Create();
  ports := TList<integer>.Create();
  names := TList<String>.Create();
end;

请随意给大卫打上“复选标记”以供回复 - 我只是详细说明了他的回复。

【讨论】:

  • 谢谢!我会试试这个:)
  • Data 应该由数据模块创建和销毁
猜你喜欢
  • 1970-01-01
  • 2017-12-07
  • 1970-01-01
  • 2013-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多