Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi TStringList - Zugriffsverletzung beim erstellen (https://www.delphipraxis.net/144001-tstringlist-zugriffsverletzung-beim-erstellen.html)

stiftII 27. Nov 2009 17:59


TStringList - Zugriffsverletzung beim erstellen
 
Hallo zusammen.

Ich experimentiere gerade mit eigenen Klassen. Jetzt hab ich ein Problem

Ich habe folgende Klasse erstellt:

Delphi-Quellcode:
  test = class
    All : TStrings;
    Male : TStringList;
    Female : TStringList;
    procedure Create;
  end;

  procedure test.Create;
  begin
    All := TStrings.Create;
    Male := TStringList.Create;
    Female := TStringList.Create;
  end;
Beim aufrufen von test.create, wird eine Zugriffsverletzung erzeugt.

Wie kann ich das vermeiden, und warum ist das so ?

Liebe Grüße,
stift

Ralf Kaiser 27. Nov 2009 18:34

Re: TStringList - Zugriffsverletzung beim erstellen
 
Du verwendest "TStrings"! Das ist eine abstrakte Basisklasse von der man keine Instanzen erstellen sollte.

Verwende hier eingach auch TStringList

Bei einer abstrakten Basisklasse werden erst einmal nur die Methoden definiert die es hinterher in einer abgeleiteten Klasse geben wird. Diese Methoden haben keinen Inhalt (also keinen Code). Der Code kommt erst in der Ableitung dazu.

Du solltest eigentlich beim compillieren des Programmes für die betreffende Zeile auch eine Compilerwarnung sehen!

stiftII 27. Nov 2009 18:54

Re: TStringList - Zugriffsverletzung beim erstellen
 
Hallo,
Bei TStringList passiert genua dasselbe :(.

-
stift

DeddyH 27. Nov 2009 18:56

Re: TStringList - Zugriffsverletzung beim erstellen
 
Das Ding heißt auch constructor.
Delphi-Quellcode:
test = class
    All : TStrings;
    Male : TStringList;
    Female : TStringList;
    constructor Create;
  end;

  constructor test.Create;
  begin
    All := TStringList.Create;
    Male := TStringList.Create;
    Female := TStringList.Create;
  end;
Und im destructor die angelegten Objekte wieder freigeben nicht vergessen.

mjustin 27. Nov 2009 18:57

Re: TStringList - Zugriffsverletzung beim erstellen
 
Zitat:

Zitat von stiftII
Hallo zusammen.

Ich experimentiere gerade mit eigenen Klassen. Jetzt hab ich ein Problem

Ich habe folgende Klasse erstellt:

Delphi-Quellcode:
  test = class
    All : TStrings;
    Male : TStringList;
    Female : TStringList;
    procedure Create;
  end;
Beim aufrufen von test.create, wird eine Zugriffsverletzung erzeugt.

Wie kann ich das vermeiden, und warum ist das so ?

test ist eine Klasse. Um eine Instanz von ihr zu benutzen, muss man sie mit einem Konstruktor erzeugen.

Create ist hier aber kein Konstruktor, sondern nur eine Prozedur.

So sieht es mit einem Konstruktor aus:
Delphi-Quellcode:
 
  Test = class
    All : TStrings;
    Male : TStrings;
    Female : TStrings;
    constructor Create;
  end;

  constructor Test.Create;
  begin
    All := TStringList.Create; <-- hier TStringlist
    Male := TStringList.Create; <-- hier TStringlist
    Female := TStringList.Create; <-- hier TStringlist
  end;
Tipp: wenn die Instanz nicht mehr benötigt und mit Free freigegeben wird, sollte auch der Speicher der für die TStrings belegt wird, über einen Destruktor freigegeben werden. Sonst entstehen Speicherlecks, die sich leicht zu Problemen anhäufen können.

Delphi-Quellcode:
 
  Test = class
    All : TStrings;
    Male : TStrings;
    Female : TStrings;
    constructor Create;
    destructor Destroy; override;
  end;
Viele Grüße,

stiftII 27. Nov 2009 19:03

Re: TStringList - Zugriffsverletzung beim erstellen
 
Danke für den Hinweis.

Es wird leider immer noch eine "Access Violation" erzeugt.

~stift

// Das ist der gesamte Code
:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type

Test = class
    All : TStrings;
    Male : TStrings;
    Female : TStrings;
    constructor Create;
  end;


  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  blub: test;
implementation

{$R *.dfm}



  constructor Test.Create;
  begin
    All := TStringList.Create;
    Male := TStringList.Create;
    Female := TStringList.Create;
  end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  blub.Create;
end;

end.

DeddyH 27. Nov 2009 19:04

Re: TStringList - Zugriffsverletzung beim erstellen
 
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
  blub := test.Create;
end;

stiftII 27. Nov 2009 19:07

Re: TStringList - Zugriffsverletzung beim erstellen
 
Ach du meine Güte ;D...

Wie konnte ich das nur übersehen :oops: .

Danke für eure nette Hilfe :).

~
stift

Ralf Kaiser 27. Nov 2009 19:43

Re: TStringList - Zugriffsverletzung beim erstellen
 
Zitat:

Zitat von DeddyH
Das Ding heißt auch constructor.

Autsch. Da war ich beim Antworten aber auch ziemlich blind! :wall:

DeddyH 27. Nov 2009 19:46

Re: TStringList - Zugriffsverletzung beim erstellen
 
Tröste Dich, ich hatte das auch nicht auf Anhieb gesehen ;)

Christian Seehase 27. Nov 2009 19:54

Re: TStringList - Zugriffsverletzung beim erstellen
 
Moin Stift,

probiers's doch mal so:
(Ich hoffe, die Kommentare helfen Dir weiter)

Delphi-Quellcode:
type
  // Wenn man von TObject ableitet ist es zwar nicht erforderlich das direkt mit anzugeben,
  // ich empfinde es aber als angenehmer die Basisklasse immer explizit anzugeben
  // TTest, da ein neuer Typ immer mit grossem T anfangen sollte
  TTest = class(TObject)

  // Interne Felder als private deklarieren, da sie nicht ausserhalb der Unit in der die
  // Klasse deklariert wurde sichtbar sein sollten (eben intern)
  // Diese sollten immer mit einem grossen F beginnen
  private
    FAll   : TStringList;
    FMale  : TStringList;
    FFemale : TStringList;

  // Was von aussen zugänglich sein soll, mit der Sichtbarkeit public versehen, damit
  // sie überall zugänglich sind, wo die Klasse instanziert wird.
  public

    // Der Konstruktor sollte auch immer so benannt werden, auch wenn es sich
    // eigentlich um eine Funktion handelt.
    constructor Create;

    // Da im Konstruktor Resourcen belegt werden müssen diese auch wieder freigegeben werden,
    // deshalb wird ein Destruktor benötigt
    destructor Destroy; override;

    // Die internen Felder nur als Eigenschaften zugänglich machen
    // Wenn es sich um Objekte handelt, die von der Klasse selber verwaltet werden, wie in
    // diesem Falle sollte man keinesfalls Schreibzugriff ermöglichen, deshalb kein write.
    property All   : TStringList read FAll;
    property Male  : TStringList read FMale;
    property Female : TStringList read FFemale;
  end;

  implementation

  constructor TTest.Create;
  begin
    // inherited ist bei der Ableitung von TObject zwar nicht notwendig, würde ich aber
    // sicherheitshalber auch hier mit angeben, falls der Constructor von TObject mal
    // mit Inhalt gefüllt wird.
    inherited;    
    FAll   := TStringList.Create;
    FMale  := TStringList.Create;
    FFemale := TStringList.Create;
  end;

  destructor TTest.Destroy;
  begin
    // Auf das ansonsten meist zu empfehlende FreeAndNil kann man hier verzichten, da
    // die internen Felder nach Abarbeitung des Destruktors in keinem Falle mehr
    // angesprochen werden.
    FAll.Free;
    FMale.Free;
    FFemale.Free;
    // Für das inherited bei Destruktor gilt hier das gleiche wie beim Konstruktor
    inherited;
  end;

stiftII 27. Nov 2009 22:55

Re: TStringList - Zugriffsverletzung beim erstellen
 
Wow, bin überwältigt.

Danke für die ausführliche Antwort!, habe ne Menge gelernt !! :)

~stift


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:41 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz