1

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

7
  • 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 (). Commented Apr 27, 2015 at 10:42
  • Please show the code where you call the IpNameData constructor. Commented Apr 27, 2015 at 10:42
  • @Nidhoegger It doesn't matter. The () can be included, or omitted. Commented Apr 27, 2015 at 10:43
  • 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. Commented Apr 27, 2015 at 11:48
  • 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. Commented Apr 27, 2015 at 11:49

2 Answers 2

3

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;
Sign up to request clarification or add additional context in comments.

2 Comments

Even though its not an error in this case, I would call Inherited in the IpNameData constructor just to avoid confusion.
@LURD I agree. And override Destroy and destroy the three lists.
0

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.

1 Comment

Data should be created and destroyed by the data module

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.