Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Fehler beim Laden von Array of record aus Datei (https://www.delphipraxis.net/14786-fehler-beim-laden-von-array-record-aus-datei.html)

Michael Leyhe 15. Jan 2004 14:46


Fehler beim Laden von Array of record aus Datei
 
Ich habe folgendes Problem:
Ich speicher ein Array of record in einer Datei.
Wenn ich diese Datei nun lade dann steht nicht mehr das im Array was dort vorher stand. :gruebel:

Hier ist der Code:

Delphi-Quellcode:

var Feld :array [1 .. 1000] of TFeld ; // TFeld ist ein record


Procedure Speichern;
var
fs:TFileStream;
begin
if SaveDialog1.Execute then begin
     fs:=TFileStream.create(SaveDialog1.FileName,fmCreate);
      try
       fs.write(feld,sizeOf(feld));
      finally
      fs.free;
      end;
  end;
end;


Procedure Laden:
var
fs:TFileStream;
begin
if openDialog1.Execute then
   begin
    if fileExists(openDialog1.FileName) then
       begin
        fs := TFileStream.create(openDialog1.FileName,fmOpenread);
        try
           if fs.size >= sizeOf(feld) then fs.read(feld,sizeOf(feld));
        finally
           fs.free;
        end;
       end else showMessage('foobar not da');
   end;
end;
Ich hoffe ihr könnt mir helfen. Danke.

choose 15. Jan 2004 14:56

Re: Fehler beim Laden von Array of record aus Datei
 
Hallo Michael,

kann es sein, dass Du in TFeld Datentypen verwendest, die auf Referenzen beruhen (zB TObject, TButton, Pointer aber auch string)?

Dann fällt mir nur noch auf, dass an dieser Stelle
Delphi-Quellcode:
fs.write(feld,sizeOf(afeld));
afeld dem Leser nicht bekannt ist. Sollte
Code:
SizeOf(afeld)<SizeOf(feld)
gelten, ist das ebenfalls ein Problem.

Michael Leyhe 15. Jan 2004 15:02

Re: Fehler beim Laden von Array of record aus Datei
 
Mit dem AFeld habe ich mich verschrieben das muss natürlich Feld heißen.

TFeld besteht aus Strings und Integer!

Michael Leyhe 15. Jan 2004 15:34

Re: Fehler beim Laden von Array of record aus Datei
 
Danke an choose und alle anderen die sich gedanken gemacht haben.
Ich habe den Fehler gefunden und mein Problem ist gelöst.

maximov 15. Jan 2004 15:35

Re: Fehler beim Laden von Array of record aus Datei
 
die zeilen kommen mir bekannt vor :-D

Zitat:

Zitat von Michael Leyhe
TFeld besteht aus Strings und Integer!

die Strings müssen limitiert sein...

Delphi-Quellcode:
text:string[128];
..denn diese records brauchen eine feste länge, was dynamische strings naturgemäss nicht haben!

cu.

choose 15. Jan 2004 15:36

Re: Fehler beim Laden von Array of record aus Datei
 
Zitat:

TFeld besteht aus Strings und Integer
Dann werden die Strings wahrscheinlich das Problem sein: Standardmäßig sind Strings in den heuten Versionen von Delphi (seit Delphi3?) als AnsiStrings abgelegt, zu denen in der OH folgendes zu finden ist:
Zitat:

Zitat von OH
Eine AnsiString-Variable ist ein Zeiger, der vier Byte Speicherplatz belegt. Wenn die Variable leer ist (also einen String der Länge Null enthält), hat der Zeiger den Wert nil, und der String belegt keinen Speicherplatz. Ist die Variable nicht leer, zeigt sie auf einen dynamisch zugewiesenen Speicherblock[..].

Da es sich bei AnsiString-Variablen um Zeiger handelt, können zwei oder mehrere dieser Variablen auf denselben Wert zeigen

Solltest Du also einen Datentyp TFeld zB in der Form
Delphi-Quellcode:
type
  TFeld = record
    AnInt: Integer;
    AString: string;
    AnotherInt: Integer;
    AnotherString: string;
  end;
wird diese Struktur lediglich
Delphi-Quellcode:
  SizeOf(Integer)+SizeOf(string)+SizeOf(Integer)+SizeOf(string)
=     4                4              4              4
16 Bytes beanspruchen, obgleich Du vielleicht Strings der Länge 300 "in" ihnen ablegen wirst. Die Stringdaten selbst liegen, wie der OH zu entnehmen ist, auf dem Heap und nicht innerhalb dieser Struktur!

Solltest Du eine solche Struktur mit TStream.Write in einen Strom schreiben, werden tatsächlich nur die Daten innerhalb der Struktur, also, im Falle der Strings, Referenzen auf Speicherbereiche auf dem Heap geschrieben.

Zu den AnsiStrings schreibt die OH weiter
Zitat:

Zitat von OH
Da dieser Speicherplatz [..] vollkommen automatisch verwaltet wird, erfordert er keinerlei Benutzercode.

und meint damit unter anderem: Es sollte keine Aussage darüber getroffen werden, wo auf dem Heap die tatsächlichen Daten liegen.

Wenn die "Logik von Delphi" entscheidet, dass die Daten nicht länger benötigt werden, und Du ein Exemplar von TFeld aus der Datei lädst, können die Referenzen auf Bereiche zeigen, die inzwischen nicht länger gültig sind. Aus diesem Grund sollten Deine Strings "komische Werte" aufweisen, während die Integers korrekt abgelegt und wieder geladen worden sind.

Eine kleine Anmerkung: Durch das Laden von Referenzen über direkten Speicherzugriff (zB TStream.Write) wird das Prinzip der Referenzzählung untergraben, so dass (möglicherweise erst zu einem späteren Zeitpunkt) Probleme bei der Verwendung von Strings auftreten können, obwohl die geschriebenen Referenzen auf gültige Bereiche auf dem Heap verweisen.

Michael Leyhe 15. Jan 2004 15:44

Re: Fehler beim Laden von Array of record aus Datei
 
@ maximov:
Dies ist mir nach der Antwort von choose auch eingefallen. :wall:


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