Delphi: создание TList, ошибка памяти

Я попытался создать 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<String>.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 выше, второй - это DataModule, называемый ServerData.

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;

Я действительно не знаю, где я должен вызвать конструктор, поэтому я позвонил при создании формы...


person Sch-Tomi    schedule 27.04.2015    source источник
comment
Действительно ли Create вызывается с помощью()? Я не программировал Delphi в течение многих лет, но я думаю помнить, что вы просто вызываете TList‹String›.Create; без ().   -  person Nidhoegger    schedule 27.04.2015
comment
Покажите код, в котором вы вызываете конструктор IpNameData.   -  person Stefan Glienke    schedule 27.04.2015
comment
@Nidhoegger Это не имеет значения. () может быть включен или опущен.   -  person David Heffernan    schedule 27.04.2015
comment
Ваше редактирование вопроса доказывает, что мое предположение было правильным. Ваш код в вопросе, который не может правильно создать объект, идентичен коду в моем ответе.   -  person David Heffernan    schedule 27.04.2015
comment
Что касается того, как создать Data, вы создаете его не в том месте. Вам нужен переопределенный конструктор и деструктор в вашем модуле данных, который имеет дело со временем жизни Data. Вы не должны делать это извне.   -  person David Heffernan    schedule 27.04.2015
comment
Вы правы @DavidHeffernan, я создал Constructor и Desctuctor, и когда я их вызываю, генерируется 3 списка ... но после этого они исчезли, я думаю, что это какая-то проблема с диапазоном, так где я должен вызвать конструктор TDataModule2.Create? :\   -  person Sch-Tomi    schedule 27.04.2015
comment
Если вы используете конструктор/деструктор, вам необходимо переопределить конструктор/деструктор в базовом классе. Ваш код уже создает модуль данных. Вероятно, с вызовом Application.CreateForm в файле .dpr. Альтернативой является использование событий OnCreate и OnDestroy модуля данных. Однако я хотел бы попросить вас вернуться к первоначальному вопросу, если это возможно. Можем ли мы завершить это?   -  person David Heffernan    schedule 27.04.2015


Ответы (2)


Код в вопросе в порядке. Неверный код - это тот, который вызывает конструктор. Готов поспорить, что там написано:

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

где следует читать:

Data := IpNameData.Create;
person David Heffernan    schedule 27.04.2015
comment
Хотя в данном случае это не ошибка, я бы вызвал Inherited в конструкторе IpNameData, чтобы избежать путаницы. - person LU RD; 27.04.2015
comment
@LURD Я согласен. И переопределить Destroy и уничтожить три списка. - person David Heffernan; 27.04.2015

Согласно ответу Дэвида + комментариям, вы должны заменить

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

to

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;

to

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

Не стесняйтесь ставить Дэвиду "галочку" для ответа - я просто подробно уточнил его ответ.

person HeartWare    schedule 27.04.2015
comment
Спасибо! Я попробую это :) - person Sch-Tomi; 27.04.2015
comment
Data должен создаваться и уничтожаться модулем данных - person David Heffernan; 27.04.2015