[Gelöst] Stream Read Länge 0 erlaubt?

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

[Gelöst] Stream Read Länge 0 erlaubt?

Beitrag von Michl »

Hi,

in einem VirtualStringTree lade ich Daten von Nodes wie folgt:

Code: Alles auswählen

procedure TForm1.GewerkeLoadNode(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Stream: TStream);
var
  Data: PGewerkData;
  aLength: Integer;
begin
  Data := Sender.GetNodeData(Node);
  if not Assigned(Data) then Exit;
 
  Stream.Read(aLength, SizeOf(aLength));
  SetLength(Data^.GewName, aLength);
  Stream.Read(Data^.GewName[1], aLength);
 
  ...
 
end;
Das hatte bisher gut funktioniert. Nun habe ich FPC Trunk aktualisiert und stelle fest, dass ich einen RunError 201 bekomme, wenn ein leerer String gespeichert wurde.

Wie gesagt, bisher ging das. Nun frage ich mich, ob dies ein Bug ist oder ob das Verhalten gewollt ist und ich selber prüfen muss, ob ein leerer String vorliegt.

So funktioniert es:

Code: Alles auswählen

  Stream.Read(aLength, SizeOf(aLength));
  SetLength(Data^.GewName, aLength);
  if aLength > 0 then
    Stream.Read(Data^.GewName[1], aLength);    
[Edit] Ich sehe gerade, das Gleiche ist bei Stream.Write.
Zuletzt geändert von Michl am Sa 2. Jan 2016, 18:51, insgesamt 1-mal geändert.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

wp_xyz
Beiträge: 5153
Registriert: Fr 8. Apr 2011, 09:01

Re: Stream Read Länge 0 erlaubt?

Beitrag von wp_xyz »

Wenn der String die Länge 0 hat, gibt es kein 1.Zeichen. Insofern finde ich das Verhalten richtig. Dass das gelegentlich keinen Fehler erzeugt, könnte daran liegen, dass die Bereichsprüfung ausgeschaltet ist. Gerade der "Default"-Buildmode von Lazarus hat diese aus. Seitdem ich häufig auch mit dem "Debug"-Buildmode arbeite, bei dem diese Prüfung aktiv ist, bekomme ich diesen Fehler immer wieder gemeldet, auch für LCL-Routinen. War auch schon vor fpc 3.0 der Fall.

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Stream Read Länge 0 erlaubt?

Beitrag von Michl »

Ja, da hast du recht. Genau das Gleiche ging mir eben auch durch den Kopf. Ohne einen String, gibt es auch kein erstes Zeichen. :oops:

Da hatte ich wohl vormals die Bereichsprüfung aus. So wird es gewesen sein.

Danke!

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Mathias
Beiträge: 6918
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: [Gelöst] Stream Read Länge 0 erlaubt?

Beitrag von Mathias »

Dafür habe ich mal ein kleinen Demo geschrieben, die zeigt was geht und was nicht.

Code: Alles auswählen

var
  fs: TFileStream;
  s: string;
begin
  fs := TFileStream.Create('Test.txt', fmCreate);
  try
    s := 'Test ';
    fs.Write(Pointer(s)^, Length(s));
    fs.Write(PChar(s)^, Length(s));
    fs.Write(s[1], Length(s));
    s := '';
    fs.Write(Pointer(s)^, Length(s));
    fs.Write(PChar(s)^, Length(s));
    fs.Write(s[1], Length(s));  // Hier knallt es
    s := 'Letzte Zeile';
    fs.Write(Pointer(s)^, Length(s));
  finally
    fs.Free;
  end;
 
  fs := TFileStream.Create('Test.txt', fmOpenRead);
  try
    s := '     ';
    fs.Read(Pointer(s)^, Length(s));
    WriteLn(s);
    fs.Read(PChar(s)^, Length(s));
    WriteLn(s);
    fs.Read(s[1], Length(s));
    WriteLn(s);
    s := '';
    fs.Read(Pointer(s)^, Length(s));
    WriteLn(s);
    fs.Read(PChar(s)^, Length(s));
    WriteLn(s);
    s := '            ';
    fs.Read(Pointer(s)^, Length(s));
    WriteLn(s);
    fs.Read(s[1], Length(s));   // Hier knallt es
  finally
    fs.Free;
  end;
end.     
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten