Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - EAccessViolation beim Erstellen von Komponenten


Bronstein - Di 12.02.08 10:58
Titel: EAccessViolation beim Erstellen von Komponenten
Hallo,
ich habe eine Funktion, die mir ein paar Button, Edits und Labels auf einem Formular dynamisch erstellt. Hier mal meine Funktion:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
procedure TForm1.FensterElemente();
var
  tmpStr: String;
  xmlDocLines: IXmlDocument;
  i, hoehe: Integer;
begin
  //Alle Elemnte von der Form löschen
  if length(ButtonArray) <> 0 then
  begin
    for i:=0 to length(ButtonArray)-1 do
    begin
      if ButtonArray[i] <> nil then
      begin

        begin
          ButtonArray[i].Free;
          ButtonArray[i] := nil;
        end
      end;
    end;
  end;
  if length(LabelArray) <> 0 then
  begin
    for i:=0 to length(LabelArray)-1 do
    begin
      if LabelArray[i] <> nil then
      begin

        begin
          LabelArray[i].Free;
          LabelArray[i] := nil;
        end
      end;
    end;
  end;
  if length(EditArray) <> 0 then
  begin
    for i:=0 to length(EditArray)-1 do
    begin
      if EditArray[i] <> nil then
      begin

        begin
          EditArray[i].Free;
          EditArray[i] := nil;
        end
      end;
    end;
  end;

  if Index = 1 then //Button für die Linienauswahl erstellen
  begin
    tmpStr := GetLines();
    DeallocXMLStrings();
    xmlDocLines := LoadXMLData(tmpStr);
    SetLength(ButtonArray, xmlDocLines.DocumentElement.ChildNodes.Count);
    hoehe := (Form1.Height - 50div xmlDocLines.DocumentElement.ChildNodes.Count;
    for i:=0 to xmlDocLines.DocumentElement.ChildNodes.Count-1  do
    begin
      ButtonArray[i] := TButton.Create(nil);
      with ButtonArray[i] do
      begin
        parent := self;
        left := 5;
        width := Form1.Width - 15;
        top := (hoehe * i)+5;
        height := hoehe;
        name := 'Button' + IntToStr(i);
        Caption := xmlDocLines.DocumentElement.ChildNodes[i].Attributes['Name'];
        onClick := ClickEvent;
        Font.Name := 'Arial';
        Font.style := [fsBold];
        font.color := RGB(12,12,255);//RGB(255, 220, 65);
        font.size := 20;
      end;
    end;
  end;
  if Index = 2 then //Button für die Linienauswahl erstellen
  begin
    SetLength(ButtonArray, 1);
    hoehe := (Form1.Height - 50div 6;
    //Speichern Button erstellen
    ButtonArray[0] := TButton.Create(nil);
    with ButtonArray[0do
    begin
      parent := self;
      left := 5;
      width := Form1.Width - 15;
      top := 0;
      height := 30;
      name := 'Button' + IntToStr(5);
      Caption := 'OK';
      onClick := ClickEvent;
      Font.Name := 'Arial';
      Font.style := [fsBold];
      font.color := RGB(12,12,255);//RGB(255, 220, 65);
      font.size := 20;
    end;
    //Labels erstellen
    SetLength(LabelArray, 2);
    LabelArray[0] := TLabel.Create(nil);
    with LabelArray[0do
    begin
      parent := self;
      left := 5;
      width := Form1.Width - 15;
      top := 100;
      //height := 20;
      name := 'Label' + IntToStr(0);
      Caption := 'Benutzername eingeben';
      Font.Name := 'Arial';
      Font.style := [fsBold];
      font.color := RGB(12,12,255);//RGB(255, 220, 65);
      font.size := 13;
    end;
    LabelArray[1] := TLabel.Create(nil);
    with LabelArray[1do
    begin
      parent := self;
      left := 5;
      width := Form1.Width - 15;
      top := 200;
      //height := 20;
      name := 'Label' + IntToStr(1);
      Caption := 'Passwort eingeben';
      Font.Name := 'Arial';
      Font.style := [fsBold];
      font.color := RGB(12,12,255);//RGB(255, 220, 65);
      font.size := 13;
    end;
    //Edits erstellen
    SetLength(EditArray, 2);
    EditArray[0] := TEdit.Create(nil);
    with EditArray[0do
    begin
      parent := self;
      left := 5;
      width := Form1.Width - 15;
      top := 300;
      height := 20;
      name := 'Edit' + IntToStr(0);
      text := '';
    end;
    EditArray[1] := TEdit.Create(nil);
    with EditArray[1do
    begin
      parent := self;
      left := 5;
      width := Form1.Width - 15;
      top := 400;
      height := 20;
      name := 'Edit' + IntToStr(1);
      text := '';
    end;
  end;
end;


Jetzt funktioniert die Funktion wenn der Index 0 ist. Ist der Index 1 dann bekomme ich folgende Fehlermeldung:
Zitat:
---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt Test.exe ist eine Exception der Klasse EAccessViolation aufgetreten. Meldung: 'Zugriffsverletzung bei Adresse 00403746 in Modul 'Test.exe'. Lesen von Adresse FFFFFFD0'. Prozeß wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
---------------------------
OK Hilfe
---------------------------


Woran könnte das liegen. Ich glaub ich habe schon alles versucht, mit "Form1", "Self", "Owner" und nil.


JayEff - Di 12.02.08 14:44

Also Konstruktoren sollten soweit ich weiß mit self (also der Form) aufgerufen werden. Da du das aber schon versucht hast, wird der Fehler woanders liegen. Gehe mal die Prozedur mit F7/F8 durch und schau, in welcher zeile der fehler auftritt und evtl bei welchem schleifendurchlauf.


zuma - Di 12.02.08 14:56

tritt der Fehler in Zeile 55 auf ??
dann liegts daran, das

xmlDocLines

einfach benutzt, aber zuvor nicht created wurde ...

ein

xmlDocLines := IXmlDocument.create(self);

könnte da helfen.


JayEff - Di 12.02.08 15:43

user profile iconzuma hat folgendes geschrieben:
einfach benutzt, aber zuvor nicht created wurde ...
Das muss es sein, hab ich übersehen. Konnte man diese Komponente nicht auf die Form ziehen? Weil davon bin ich ausgegangen, ohne zu sehen, dass es ja eine lokale variable ist. Die ist nicht instantiiert, fehler wie zuma gesdagt hat beheben aber am ende ein Komponente.Free nicht vergessen!

Ausserdem kannst du doch FreeAndNil(Button[i]) einsetzen statt Button[i].Free; Button[i]:=nil; :nixweiss: