[Delphi] Exception

Daradon

Cadet 1st Year
Registriert
Mai 2004
Beiträge
15
hi ... hab (mal wieder :( ) ein problem, und zwar löst der quellcode:

Code:
unit Unit1;

interface

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

type
  TItem = class
    gold_value : String;

    end;
  TForm1 = class(TForm)
    OpenDialog1: TOpenDialog;
    Button1: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

uses StrUtils;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
 datei : TextFile;
 zeile : String;
 m, i, i2 : Integer;
 item : array [0..10] of TItem;
begin

if not Opendialog1.Execute then
  exit;

{$I-}
AssignFile(datei,Opendialog1.FileName);
reset(datei);

i := 0;

if IOResult = 0 then
begin
  while not EOF(datei) do
  begin
    ReadLn(datei,zeile);
    if AnsiContainsText(zeile,'gold_value') then
      if Pos('gold_value',Zeile)<> 0 then
      begin
        Item[i].Create;
        m:= Pos('=',Zeile);
        Item[i].gold_value :=copy(Zeile,m+1,Length(Zeile)-m);
        Listbox1.Items.add('Item :' + IntToStr(i) + ' gold_value = ' + Item[i].gold_value);
      end;
        Inc(i);
  end;
  {$I+}
  closefile(datei);

  for i2 :=0 to i do
  Item[i2].free;


end;



end;

end.

Diese Exception aus:
---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt Project1.exe ist eine Exception der Klasse EAccessViolation aufgetreten. Meldung: 'Zugriffsverletzung bei Adresse 004039D3 in Modul 'Project1.exe'. Lesen von Adresse FFFFFFF6'. Prozess wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
---------------------------
OK Hilfe
---------------------------

nach dem 4ten durchlauf der while kommt die Exception .. nur ich weiß nicht warum .. hab ich etwas übersehen ?

edit:

genauer noch: sobald m:= Pos('=',Zeile); ausgeführt wird kommt der fehler
( gold_value = 260; ) findet delphi dabei
 
Zuletzt bearbeitet:
Schreib mal:

Code:
Item[ i] := TItem.Create;

so sollte es richtig sein. Mmh und du erhöhst dein i bei jedem Durchlauf. Ich denke mal, das willst Du nur, wenn auch eine Zeile mit [gold_value] gefunden wird.
 
Zuletzt bearbeitet:
ja hab das mit dem i schon geändert :)

begin
Item := TItem.Create;
m:= Pos('=',Zeile);
Item.gold_value :=copy(Zeile,m+1,Length(Zeile)-m);
Listbox1.Items.add('Item :' + IntToStr(i) + ' gold_value = ' + Item.gold_value);
Inc(i);
end;

Item := TItem.Create erzeugt auch den fehler
 
Das muss bedeuten, dass i wohl schon größer als das Array ist. Schau Dir mal den Wert von i bei der Zuweisung Item := TItem.Create; an. Wenn er größer als 10 ist, greifst Du im Speicher daneben.
 
so ich hab jetzt mal aus dem TItem ein dynamischen array gemacht:

Code:
procedure TForm1.Button1Click(Sender: TObject);
var
 datei : TextFile;
 zeile : String;
 m, i, i2 : Integer;
 item : array of TItem;
begin

if not Opendialog1.Execute then
  exit;

{$I-}
AssignFile(datei,Opendialog1.FileName);
reset(datei);

i := 1;

SetLength(item,1);

if IOResult = 0 then
begin
  while not EOF(datei) do
  begin
    ReadLn(datei,zeile);
    if AnsiContainsText(zeile,'gold_value') then
      if Pos('gold_value',Zeile)<> 0 then
      begin
        Item[i] := TItem.Create;
        m:= Pos('=',Zeile);
        Item[i].gold_value :=copy(Zeile,m+1,Length(Zeile)-m);
        Listbox1.Items.add('Item :' + IntToStr(i) + ' gold_value = ' + Item[i].gold_value);
        Inc(i);
        SetLength(item,i+1);
      end;

  end;
  {$I+}
  closefile(datei);

  for i2 :=0 to i do
  Item[i2].free;


end;



end;

kommt noch immer der selbe fehler ..
PS.: das erste mal das ich mit SetLenght arbeite .. hoffe ich verwende das richtig
 
Hmm kannst Du mal die Datei, die Du einliest, posten oder als Anhang dranpappen? Dann debugge ich mal bei mir. Auf den ersten Blick seh ich's jetzt nicht.

Hmm ich glaub, ich sehs doch grad. Also SetLength ist erstmal grundsätzlich okay. Das Problem ist aber, dass ein dynamisches Array immer bei 0 anfängt. Da das i aber schon 1 ist, geht der Zugriff schief.
 
Zuletzt bearbeitet:
ob 1 oder 0 ist hier egal wies scheint .. hatte zuerst 0 .. und habs dann mit 1 versucht :(

hier mal die datei
 

Anhänge

  • test.txt
    1,7 KB · Aufrufe: 461
Mir wäre jetzt nicht bewusst, dass ich irgendwas geändert hätte. Aber so läuft es bei mir durch:
Code:
procedure TForm1.Button1Click(Sender: TObject);
var
 datei : TextFile;
 zeile : String;
 m, i, i2 : Integer;
 item : array of TItem;
begin

  if not Opendialog1.Execute then
    exit;

  {$I-}
  AssignFile(datei,Opendialog1.FileName);
  reset(datei);

  i := 0;

  SetLength(item,1);

  if IOResult = 0 then
  begin
    while not EOF(datei) do
    begin
      ReadLn(datei,zeile);
      if AnsiContainsText(zeile,'gold_value') then
        if Pos('gold_value',Zeile)<> 0 then
        begin
          Item[i] := TItem.Create;
          m:= Pos('=',Zeile);
          Item[i].gold_value :=copy(Zeile,m+1,Length(Zeile)-m);
          Listbox1.Items.add('Item :' + IntToStr(i) + ' gold_value = ' + Item[i].gold_value);
          Inc(i);
          SetLength(item,i+1);
        end;

    end;
    {$I+}

    for i2 :=0 to i do
    Item[i2].free;
  end;
  closefile(datei);
end;

Achso, die Länge eines dynamischen Arrays kannst Du übrigens wie bei einem String mit Length feststellen
 
komisch .. mh.. ich hab delphi 7 schülerversion .. kanns daran liegen ?

und hat wenigstens das einfügen in die listbox funktioniert ?

Edit:

komisch als ich deinen code verwendet habe gings bei mir auch :o
 
Zuletzt bearbeitet:
Ne an der Schülerversion sollte es nicht liegen.

Übrigens kann man solchen Fehlern schneller auf die Spur kommen :) Geh mal auf Projekt->Optionen, dann zum Reiter Compiler. Dort solltest Du ein Häkchen bei "Bereichsprüfung" machen. Überlaufprüfung kann auch nie schaden. Durch diese Optionen wird das Programm zwar ein wenig langsamer, aber das ist in so einer Anwendung nicht feststellbar. Dafür bekommst Du dann aber wesentlich bessere Fehlermeldungen, wenn etwas schief geht :)
 
ich hab jetzt gefunden was der unterschied war,

closefile() war bei mir noch in der if die prüft ob ein exception da ist ,
wobei ichs komisch finde das setlenght 0 einen error gibt

bin etwas verwirrt lol
 
Zuletzt bearbeitet:
SetLength (0) sollte gehen. Ist aber das selbe, als wenn Du dem dynamischen Array nil zuweist. Ich hatte auch noch den Startwert von i von 1 auf 0 gesetzt. Hmm naja, jetzt läufts ja :-)
 
:( noch neine frage ( ich versprech die letzte für heut :) )

Bei diesem code:

Code:
unit Unit1;

interface

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

type
  TItem = class
    gold_value, template_name : String;

    end;
  TForm1 = class(TForm)
    OpenDialog1: TOpenDialog;
    Button1: TButton;
    ListBox1: TListBox;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

uses StrUtils;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
 datei : TextFile;
 zeile : String;
 m, i, i2, i3 : Integer;
 item : array of TItem;
begin

  if not Opendialog1.Execute then
    exit;

  {$I-}
  AssignFile(datei,Opendialog1.FileName);
  reset(datei);

  i := 0; // zähler für Item
  i2:= 0; // zähler für Free
  i3:= 0; // zähler für Schleife
  SetLength(item,1);

  if IOResult = 0 then
  begin
    while not EOF(datei) do
    begin
      ReadLn(datei,zeile);
      inc(i3);

      { gold_value }
      if AnsiContainsText(zeile,'gold_value') then
        if Pos('gold_value',Zeile)<> 0 then
        begin
          Item[i] := TItem.Create;
          m:= Pos('=',Zeile);
          Item[i].gold_value :=copy(Zeile,m+1,Length(Zeile)-m-1);
          Listbox1.Items.add('Item :' + IntToStr(i) + ' gold_value = ' + Item[i].gold_value);
        end
      else   // wenn nicht 'gold_value' dann nach 'template_name'
        begin
      { template_name }
      if AnsiContainsText(zeile,'template_name') then
        if Pos('template_name',Zeile)<> 0 then
        begin
          Item[i] := TItem.Create;
          m:= Pos('=',Zeile);
          Item[i].template_name :=copy(Zeile,m+1,Length(Zeile)-m-1);
          Listbox1.Items.add('Item :' + IntToStr(i) + ' template_name = ' + Item[i].template_name);
        end;
      end;


      Inc(i);
      SetLength(item,i+1);

    end;
    {$I+}

    for i2 := 0 to i do
    Item[i2].free;
  end;
  closefile(datei);
end;

end.

wird für jedes item eine neue instanz erzeugt .. aber ich möchte das zuerst alle felder einer instanz gefüllt sind bis delphi die nächste erzeugt .. wie könnte ich das am geschicktesten umsetzten ?

hab in der delphi help bissl nachgeforscht aber keine methode gefunden die mir den "Füllstand" anzeigen kann
 
Zuletzt bearbeitet:
Hmmm meinst Du, dass beim ersten Durchlauf gold_value, im Zweiten dann template_name gefüllt wird, und erst danach das nächste TItem erzeugt wird usw? So einen 'Füllstand' kannst Du Dir leider nur selbst implementieren.
 
Zurück
Oben