Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi AV bei Records laden (https://www.delphipraxis.net/72246-av-bei-records-laden.html)

Neutral General 27. Jun 2006 16:30


AV bei Records laden
 
Hi,

Also erst mal meine Records:
Delphi-Quellcode:
rZinsen = packed record
 Start   : TDateTime;
 Intervall: Zinsintervall;
 Kind    : Zinsart;
 Value   : Word;
end;

rSchulden = packed record
 Bei   : String;
 Anlass : String;
 Betrag : Single;
 Zinsen : rZinsen;
 Gezahlt: Boolean;
end;
dann hab ich ne Klasse die die Schulden verwaltet:

Delphi-Quellcode:
TSchuldenliste = class
   private
    FStringgrid: TStringgrid;
    FItems: Array of rSchulden;
    FCount: Word;
    function GetItem(Index: Integer): rSchulden;
    procedure SetItem(Index: Integer; const Value: rSchulden);
   public
    constructor Create(Stringgrid: TStringgrid);
    procedure Add(Schulden: rSchulden);
    property Items[Index: Integer]: rSchulden read GetItem write SetItem;
    property Count: Word read FCount write FCount;
    procedure SaveToFile(Filename: String);
    procedure LoadFromFile(Filename: String);
  end;
und beim Laden von den Records gibts jetzt irgendwie beim zweiten Record einen Fehler.. das erste wird fehlerlos geladen (was heißt das es eigentlich nicht am speichern liegen kann.. weshalb ich die Speichern Procedure jetzt aus Platzgründen erst mal nicht poste).

Delphi-Quellcode:
procedure TSchuldenliste.LoadFromFile(Filename: String);
var MS: TMemoryStream;
    i, len: Integer;
begin
  MS := TMemoryStream.Create;
  Ms.LoadFromFile(Filename);
  Ms.Position := 0;

  Ms.Read(FCount, SizeOf(Word));
  SetLength(FItems,FCount);

  for i:= 0 to FCount-1 do begin
   Ms.Read(Len, SizeOf(Integer));
   SetLength(FItems[i].Bei,len);
   Ms.Read(FItems[i].Bei[1], len);
   Ms.Read(Len, SizeOf(Integer));
   SetLength(FItems[i].Anlass,len);
   Ms.Read(FItems[i].Anlass[1], len);
   Ms.Read(FItems[i].Betrag, SizeOf(Single));
   Ms.Read(FItems[i].Zinsen.Start, SizeOf(Double));
   Ms.Read(FItems[i].Zinsen.Intervall, SizeOf(Zinsintervall));
   Ms.Read(FItems[i].Zinsen.Kind, SizeOf(Zinsart));
   Ms.Read(FItems[i].Zinsen.Value, SizeOf(Integer));
   Ms.Read(FItems[i].Gezahlt, SizeOf(Boolean));
  end;
 
  Ms.Free; // Mit try-except etc hab ichs nicht so :D
end;
Wo liegt das Problem ? :(
Das Array FItems ist auch groß genug nach SetLength.. Aber was läuft denn da falsch ? :(

PS: Ach ja der Debugger bleibt bei beim zweiten mal beim ersten SetLength stehn...

Gruß
Neutral General

SirThornberry 27. Jun 2006 17:05

Re: AV bei Records laden
 
folgendes ist ganz gefährlich:
Delphi-Quellcode:
FCount-1
Wenn FCount mal 0 ist ergibt "FCount - 1" einen Überlauf (oder nennt man das dann unterlauf?) und schon ist das Ergebnis recht groß und die Schleife wird zu oft ausgeführt.
Declariere FCount also lieber als Integer.

Die Speichernroutine würde fände ich doch recht nützlich. Ich hab das Gefühl das Speichern und laden übereinstimmen. Das erste laden kann klappen weil eventuell schon aus dem zweiten item gelesen wird. Beim zweiten Lesen liest du dann eventuell über den Stream hinaus.

Neutral General 27. Jun 2006 17:15

Re: AV bei Records laden
 
Mh ok.
Aber das bringt mich leider bei meinem Problem nicht weiter :(
Was mir auch aufgefallen ist bei der Speichern procedure (poste sie doch mal):

Delphi-Quellcode:
procedure TSchuldenliste.SaveToFile(Filename: String);
var MS      : TMemoryStream;
    i, len  : Integer;
begin
  MS := TMemoryStream.Create;
  // Anzahl der Einträge speichern
  Ms.Write(Count, SizeOf(Integer));

  for i:= 0 to Count-1 do begin
   len := Length(Items[i].Bei);
   Ms.Write(len, SizeOf(Integer));
   Ms.Write(Items[i].Bei[1], len);
   len := Length(Items[i].Anlass);
   Ms.Write(len, SizeOf(Integer));
   Ms.Write(FItems[i].Anlass[1], len);
   Ms.Write(FItems[i].Betrag, SizeOf(Single));
   Ms.Write(FItems[i].Zinsen.Start, SizeOf(Double));
   Ms.Write(FItems[i].Zinsen.Intervall, SizeOf(Zinsintervall));
   Ms.Write(FItems[i].Zinsen.Kind, SizeOf(Zinsart));
   Ms.Write(FItems[i].Zinsen.Value, SizeOf(Integer));
   Ms.Write(FItems[i].Gezahlt, SizeOf(Boolean));
  end;

  Ms.SaveToFile(Filename);
  Ms.Free;
end;
Wenn ich bei den Strings statt Items[i].Bei/Anlass FItems[i].Bei/Anlass benutze dann gibts schon beim speichern ne AV.. was ich irgendwie auch nicht verstehe.. bei allen anderen Variablen meckert der Compiler schon bei Items.Irgendwas weils kein var Parameter ist... Und bei den Strings klappts und man bekommst sogar Ärger wenn man FItems benutzt (AV).. :gruebel:

Gruß
Neutral General

Mavarik 27. Jun 2006 17:17

Re: AV bei Records laden
 
Warum nimmst Du den einen Stream, wenn Du ein Record hast?
Da kannst Du den Record doch viel besser direkt speichern....

Frank

Neutral General 27. Jun 2006 17:18

Re: AV bei Records laden
 
wie denn ?
Also ich hab im Forum geguckt und hab irgendwo gelesen das

Delphi-Quellcode:
Stream.WriteBuffer(Record, SizeOf(Recordtyp));
nicht funktioniert wenn im Record en String drin ist..

Hawkeye219 27. Jun 2006 17:24

Re: AV bei Records laden
 
Zinsen.Value ist als Word deklariert, wird aber als Integer gelesen und gespeichert!

@SirThornberry
Ein Fehler tritt nur dann auf, wenn die Schleifenvariable eine vorzeichenlose Variable ist. Falls sie - wie im obigen Code geschehen - als vorzeichenbehaftete Variable deklariert wird, behandelt der Compiler auch die Grenzen als vorzeichenbehaftete Werte.

Vermeiden sollte man solche Konstruktionen trotzdem.

Gruß Hawkeye

Mavarik 27. Jun 2006 17:27

Re: AV bei Records laden
 
[/delphi]
Zitat:

Zitat von Neutral General
wie denn ?

Na so...:

Delphi-Quellcode:
{$A1}
var
  F : File of rSchulden;
Fd : file;
  S : rSchulden;
SA : array[0..9999] of rSchulden;
begin
  assignfile(f,'Mydat.dat');
  rewrite(f); // Reset

  for i:=0 to xyp do
   write(f,S);

  Closefile;
  // Oder
  assignfile(fd,'Mydat.dat');

  rewrite(fd,sizeof(RSchulden));
  Blockwrite(fd,SA[0],10000);
  Closefile(fd);

*Ungetestet nur getippt...

Frank :coder:

Neutral General 27. Jun 2006 17:27

Re: AV bei Records laden
 
Oh das könnte das Problem sein! Mit Sicherheit ist das das Problem :)
Ich verbesser es mal.

EDIT: Hehe genau daran hats gelegen thx :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:12 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