Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Zugriff auf Record-Eigenschaft nicht möglich (https://www.delphipraxis.net/134086-zugriff-auf-record-eigenschaft-nicht-moeglich.html)

CalganX 15. Mai 2009 10:15


Zugriff auf Record-Eigenschaft nicht möglich
 
Hallo zusammen,

ich habe folgendes Record:
Delphi-Quellcode:
AWSTRING = record
  len: int32_t;
  value: WideString;
end;
Nun will ich mit Hilfe eines File-Streams aus einer Datei dieses Record füllen:
Delphi-Quellcode:
function fread_AWSTRING(var destination: AWSTRING; const fs: TFileStream): size_t;
var
  temp: uint16_t;
  i: integer;
begin
  Result := fread_be_int32(destination.len, 1, fs);
  if ((destination.len) > 0) then begin
    destination.value := StringOfChar(#00, destination.len);
    for i := 0 to destination.len - 1 do begin
      fread_be_uint16(temp, 1, fs);
      destination.value[i+1] := WideChar(temp);
    end;
  end;
end;
In Zeile 8 schmeißt mir der Debugger aber eine Zugriffsverletzung um die Ohren. Und das ist unabhängig davon, was ich da mache. Jeder Zugriff auf destination.value schlägt fehl, während der Zugriff auf destination.len möglich ist. Auch wenn ich Zeile 8 ganz weg lasse, kriege ich bei destination.value[i+1] := WideChar(temp); eine Zugriffsverletzung (temp hat mit 101 aber einen korrekten Wert - daran kann es also nicht liegen).

Kann sich das jemand bzw. mir erklären?

Gruß
Christopher

PS: Das analoge Einlesen eines Strings (destination.value hat da den Typ String) funktioniert problemlos.

mkinzler 15. Mai 2009 10:22

Re: Zugriff auf Record-Eigenschaft nicht möglich
 
Da WideString nicht finalisierbar istr steht bei Value nur ein Zeiger. du müsstest mit einer Hilfsvariablen arbeiten

himitsu 15. Mai 2009 10:24

Re: Zugriff auf Record-Eigenschaft nicht möglich
 
versuch mal statt StringOfChar ein
Delphi-Quellcode:
SetLength(destination.value, destination.len);

CalganX 15. Mai 2009 10:28

Re: Zugriff auf Record-Eigenschaft nicht möglich
 
Hallo,

Zitat:

Zitat von himitsu
Delphi-Quellcode:
SetLength(destination.value, destination.len);

wie gesagt: Es ist unabhängig davon, was ich in Zeile 8 mache. Habe SetLength schon probiert und führt zum gleichen Fehler.

Zitat:

Zitat von mkinzler
Da WideString nicht finalisierbar istr steht bei Value nur ein Zeiger. du müsstest mit einer Hilfsvariablen arbeiten

Ganz so einfach scheint das aber auch nicht zu gehen.
Delphi-Quellcode:
function fread_AWSTRING(var destination: AWSTRING; const fs: TFileStream): size_t;
var
  temp: uint16_t;
  i: integer;
  temps: WideString;
begin
  Result := fread_be_int32(destination.len, 1, fs);
  if ((destination.len) > 0) then begin
    SetLength(temps, destination.len);
    for i := 0 to destination.len - 1 do begin
      fread_be_uint16(temp, 1, fs);
      temps[i+1] := WideChar(temp);
    end;
    destination.value := temps;
  end;
end;
Da fliegt mit in der letzten Zeile eine EOutOfMemory-Exception um die Ohren. :shock:

Gruß
Christopher

jbg 15. Mai 2009 11:13

Re: Zugriff auf Record-Eigenschaft nicht möglich
 
Kann es sein, dass der Aufrufer der Funktion bereits einen defekten destination Parameter reingibt, also der WideString auf eine undefinierte Speicheradresse zeigt?

CalganX 15. Mai 2009 11:20

Re: Zugriff auf Record-Eigenschaft nicht möglich
 
Hallo jbg,

das Rekord ist in keiner Weise initialisiert. D.h. es ist einfach eine lokale Variable in einer Prozedur, die durch drei Aufrufe bis an fread_AWSTRING gegeben wird:

Delphi-Quellcode:
type
  generic_data_header = record
    data_type_id: ASTRING;
    unique_file_id: ASTRING;
    date_time: AWSTRING;
    locale: AWSTRING;
    n_name_type_value: int32_t;
    name_type_value: array of nvt_triplet;
    n_parent_headers: array of Pointer;
  end;

function Read_Generic(const filename: string): boolean;
var
  fs: TFileStream;
  my_data_header: generic_data_header;
begin
  Result := false;

  fs := TFileStream.Create(filename, fmOpenRead or fmShareDenyNone);
  try
    read_generic_data_header(my_data_header, fs);
  finally
    FreeAndNil(fs);
  end;

  Result := true;
end;

function read_generic_data_header(var data_header: generic_data_header; fs: TFileStream): integer;
begin
  Result := fread_ASTRING(data_header.data_type_id, fs) or
            fread_ASTRING(data_header.unique_file_id, fs) or
            fread_AWSTRING(data_header.date_time, fs) or
            fread_AWSTRING(data_header.locale, fs);
end;
Da wir uns aber ja unter Delphi befinden, habe ich nicht den Drang verspürt für den WideString großartig Speicher zu belegen. Wenn ich eine lokale Widestring-Variable, die nicht in einem Array ist, fülle, dann brauche ich ja auch nix zu belegen, sondern es funktioniert dank Compiler-Magic.

Gruß
Christopher

Stevie 15. Mai 2009 12:02

Re: Zugriff auf Record-Eigenschaft nicht möglich
 
Die Methode fread_AWSTRING hat imo keinen Fehler, es könnte eher an fread_be_int32 oder fread_be_uint16 liegen. Liefern die das richtige zurück? (Länge des auszulesenden Strings und einzelne Zeichen)

CalganX 15. Mai 2009 12:53

Re: Zugriff auf Record-Eigenschaft nicht möglich
 
Hallo Stefan,

ja, eigentlich schon. Und der Fehler passiert ja direkt beim ersten Zugriff auf destination.value.

Ich bin nur jetzt nicht mehr im Büro - erst am Montag wieder. Ich gucke dann noch mal drüber.

Gruß
Christopher

Stevie 15. Mai 2009 15:03

Re: Zugriff auf Record-Eigenschaft nicht möglich
 
Poste dann mal bitte ein kleines Programm, in dem der Fehler nachstellbar ist, mein Test mit einem solchen Record schlug nämlich nicht fehl. (Delphi7)

CalganX 18. Mai 2009 08:23

Re: Zugriff auf Record-Eigenschaft nicht möglich
 
Hallo,

das Problem liegt wohl nicht in den fread_*-Methoden. Greife ich nämlich noch vor dem Lesen auf die Eigenschaft zu:
Delphi-Quellcode:
function read_generic_data_header(var data_header: generic_data_header; fs: TFileStream): integer;
begin
  fread_ASTRING(data_header.data_type_id, fs);
  fread_ASTRING(data_header.unique_file_id, fs);
  fread_AWSTRING(data_header.date_time, fs); // Hier wird nix gelesen, da die Länge = 0 ist
  data_header.locale.value := '-----'; // <--- hier kommt die Exception
  fread_AWSTRING(data_header.locale, fs);

  Result := 1;
end;
Erhalte ich schon dort eine EOutOfMemory-Exception.

Noch mal die Typ-Definitionen:
Delphi-Quellcode:
type
  // C-Typedefs
  int8_t = Shortint;
  uint8_t = Byte;
  int16_t = Smallint;
  uint16_t = Word;
  int32_t = integer;
  uint32_t = longword;
  float32_t = Single;
  uchar = uint8_t;

  AWSTRING = record
    len: int32_t;
    value: WideString;
  end;

  generic_data_header = record
    data_type_id: ASTRING;
    unique_file_id: ASTRING;
    date_time: AWSTRING;
    locale: AWSTRING;
    n_name_type_value: int32_t;
    name_type_value: array of nvt_triplet;
    n_parent_headers: array of Pointer;
  end;
Irgendwelche Vorschläge?

Gruß
Christopher

PS: Ich weiß im Moment nicht, wie ich ein Beispielprogramm bereit stellen sollen, da ich die Datei, aus der gelesen werden soll, nicht veröffentlichen kann.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:31 Uhr.
Seite 1 von 2  1 2      

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