1
votes

I tried to create 3 TList but, when i'm creating them i got error.

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

So the problem happen when program reach ips := TList<String>.Create();, and i get:

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

I can not figure out what am i doing wrong :\

EDIT

Well its a little bit messy for me...

But i have 3 files, ipname is upper, second one is a DataModule called 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;

And the last one is the 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;

I dont really know where should i call the constructor so i called when form is created...

2
Does Create really get called with ()? I didnt code Delphi for years now, but i think to remember that you just call TList<String>.Create; without ().Nidhoegger
Please show the code where you call the IpNameData constructor.Stefan Glienke
@Nidhoegger It doesn't matter. The () can be included, or omitted.David Heffernan
Your edit to the question proves that my guess was correct. Your code in the question that fails to create the object correctly is identical to the code in my answer.David Heffernan
As for how to create Data, you are creating it in the wrong place. You need an overridden constructor and destructor in your data module that deals with the lifetime of Data. You should not be doing that from the outside.David Heffernan

2 Answers

3
votes

The code in the question is fine. The code that is wrong is that which calls the constructor. I am prepared to bet that it reads:

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

where it should read:

Data := IpNameData.Create;
0
votes

As per David's reply + comments, you should replace

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

with

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

and update

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;

and add

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

and change

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;

Feel free to give David the "Checkmark" for reply - I have merely specified his reply in detail.