Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Die Delphi-IDE (https://www.delphipraxis.net/62-die-delphi-ide/)
-   -   Fehlertoleranz DELPHI, TEIL #2 (https://www.delphipraxis.net/171911-fehlertoleranz-delphi-teil-2-a.html)

bernhard_LA 1. Dez 2012 08:26

Fehlertoleranz DELPHI, TEIL #2
 
wir haben in unserem Team folgende Funktion aus dem Internet gefunden, angepasst und in einer unit implementiert die dann in mehreren Anwendungen verwendet wird.



Delphi-Quellcode:

procedure LoadStringFromFile(Filename: string; var LoadString: string);
var
  fs: TFileStream;
begin
  fs := TFileStream.Create (Filename, fmOpenRead or fmShareDenyNone);
  try
    SetLength (LoadString, fs.Size);
    if fs.size>0 then
      fs.Read (LoadString[1], fs.Size);
  finally
    fs.Free;
  end;
end;

Beim Kopieren dieser Funktion aus dem Internet ist uns ein kleiner Fehler unterlaufen, wir haben beim Rückgabeparameter das var vergessen.

Delphi-Quellcode:

procedure LoadStringFromFile(Filename: string; LoadString: string);

bei zwei Anwendungen hat dieser Code fehlerfrei funktioniert, bei der dritten Anwendung haben wir beim Debuggen dann unseren Fehler entdeckt und behoben.
Die Frage ist nur " Warum hat dieser fehlerhafte Code trotzdem funktioniert ????"

Desmulator 1. Dez 2012 08:35

AW: Fehlertoleranz DELPHI, TEIL #2
 
Im ersten Moment fällt mir nur ein, dass Strings ja auch lediglich nur pointer sind und die eigentlichen Zeichen, sowie die Länge schon per Referenz übergeben werden. Also werden auch Manipulationen an den selben String durchgeführt. Vielleicht ist beim dritten Programm mehr Compilermagic am Werk und der String wird zunächst kopiert?

Uwe Raabe 1. Dez 2012 08:36

AW: Fehlertoleranz DELPHI, TEIL #2
 
Nur eine Vermutung: die automatische Referenzzählung bei Strings wirkt nur bei direkten Zuweisungen? Daher arbeitet das SetLength mit dem übergebenen StringPointer (das TStream.Read macht das sowieso).

Sir Rufo 1. Dez 2012 08:40

AW: Fehlertoleranz DELPHI, TEIL #2
 
Aus dem gleichen Grund, warum man bei einer reinen Übergabe von einem
Delphi-Quellcode:
string
das mit
Delphi-Quellcode:
const
machen sollte.

Es funktioniert, wenn der
Delphi-Quellcode:
string
Parameter vor der Übergabe an die Funktion mit genug Daten gefüllt war.

Ich hätte hier aber den Parameter eher als
Delphi-Quellcode:
out
und nicht als
Delphi-Quellcode:
var
deklariert.
Von der reinen Funktion macht es keinen Unterschied, somit ist aber dokumentiert, das der Wert in dem Parameter die Funktion nicht beeinflusst.

sx2008 1. Dez 2012 08:44

AW: Fehlertoleranz DELPHI, TEIL #2
 
Mal unabhängig von der Ursachenforschung; die korrekte Funktion sieht so aus:
Delphi-Quellcode:
function LoadStringFromFile(const Filename: string):AnsiString;
var
  fs: TFileStream;
begin
  fs := TFileStream.Create (Filename, fmOpenRead or fmShareDenyNone);
  try
    SetLength(Result, fs.Size);
    if fs.size>0 then
      fs.ReadBuffer(Result[1], Length(Result));
  finally
    fs.Free;
  end;
end;
Als Funktion lässt sich der Code im Gegensatz zur Prozedur aus dem 1. Beitrag flexibler einsetzen.

himitsu 1. Dez 2012 08:59

AW: Fehlertoleranz DELPHI, TEIL #2
 
Auch wenn sx2008 unbewust die Lösung verbaut hat.

D2009 + String + Unicode?

Nachdem nun schon über 3 Jahre lang alle darüber schreiben, daß nun ein String nicht mehr ANSI, sopnder unicode ist, dürften das langsam mal bekannt werden, vorallem da die Sunchfunktion mit entsprechenden Beiträgen überfüllt sein dürfte.


Und die Frage nach dem Warum:
Wenn man Glück hat, dann gibt es nur eine Referenz und im Stream sind genau doppelt soviele Daten (Bytes), wie Daten im String (Bytes),
also genausoviele Bytes im Stream, wie Chars (je 2 Bytes) m String,
denn dann macht SetLength nämlich garnichts.
Und wenn dann beim Zugriff auf den String ebenfalls nichts mit der Referenzierung passiert, dann wird direkt in den externen String geschrieben.
(aber eigentlich sollte nur bei CONST eine passende Referenz reinkommen :gruebel:)

himitsu 1. Dez 2012 09:06

AW: Fehlertoleranz DELPHI, TEIL #2
 
[del]

Popov 1. Dez 2012 09:14

AW: Fehlertoleranz DELPHI, TEIL #2
 
Zitat:

Zitat von sx2008 (Beitrag 1193827)
Mal unabhängig von der Ursachenforschung; die korrekte Funktion sieht so aus:

Mal unabhängig von der Ursachenforschung; die ursprüngliche Funktion aus dem Internet hatte Boolean als Rückgabewert, und die sagte einem ob die Funktion erfolgreich war. Man kann auch String als Rückgabewert nehmen, muss dann aber selbst auf Erfolg prüfen.

sx2008 1. Dez 2012 09:24

AW: Fehlertoleranz DELPHI, TEIL #2
 
Zitat:

Zitat von Popov (Beitrag 1193832)
die ursprüngliche Funktion aus dem Internet hatte Boolean als Rückgabewert, und die sagte einem ob die Funktion erfolgreich war

Das ist eine schlechte Technik (siehe Thread http://www.delphipraxis.net/171901-f...ml#post1193831).
Ich habe oben noch den Aufruf von Read() nach ReadBuffer() geändert.
Somit ist gewährleistet, dass die Funktion entweder mit dem String zurückkehrt oder eine Exception liefert.
Der einzige Schwachpunkt wären Dateien die grösser sind als der String an Daten aufnehmen kann (2/4GB-Limit).

himitsu 1. Dez 2012 09:32

AW: Fehlertoleranz DELPHI, TEIL #2
 
Dann wirft SetLength eine schöne Exception und man hat ebenfalls ein passendes Ergebnis.

Nja, aber du meinst 1, bzw 1.5 GB (4 GB nicht, denn das ist nicht umsonst eine 3GB-Option), denn dre String braucht einen zusammenhängenden Speicherblock.


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