![]() |
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 ????" |
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?
|
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).
|
AW: Fehlertoleranz DELPHI, TEIL #2
Aus dem gleichen Grund, warum man bei einer reinen Übergabe von einem
Delphi-Quellcode:
das mit
string
Delphi-Quellcode:
machen sollte.
const
Es funktioniert, wenn der
Delphi-Quellcode:
Parameter vor der Übergabe an die Funktion mit genug Daten gefüllt war.
string
Ich hätte hier aber den Parameter eher als
Delphi-Quellcode:
und nicht als
out
Delphi-Quellcode:
deklariert.
var
Von der reinen Funktion macht es keinen Unterschied, somit ist aber dokumentiert, das der Wert in dem Parameter die Funktion nicht beeinflusst. |
AW: Fehlertoleranz DELPHI, TEIL #2
Mal unabhängig von der Ursachenforschung; die korrekte Funktion sieht so aus:
Delphi-Quellcode:
Als Funktion lässt sich der Code im Gegensatz zur Prozedur aus dem 1. Beitrag flexibler einsetzen.
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; |
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:) |
AW: Fehlertoleranz DELPHI, TEIL #2
[del]
|
AW: Fehlertoleranz DELPHI, TEIL #2
Zitat:
|
AW: Fehlertoleranz DELPHI, TEIL #2
Zitat:
![]() 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). |
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. |
AW: Fehlertoleranz DELPHI, TEIL #2
Laut Dokumentation kann ein String in Delphi maximal 2 GB belegen - unabhängig von eventuell höherem Speicherausbau oder 32/64-Bit Compiler. Die Anzahl der möglichen Zeichen und somit der maximale Wert für SetLength ergibt sich daraus. Dabei muss der benötigte Speicher für String-Verwaltung (Länge, Referenz-Zählung) evtl. noch berücksichtigt werden.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:58 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz