![]() |
AW: Procedure vs Function, Vor- und Nachteile
Interessantes Beispiel was Himitsu da gepostet hat
Delphi-Quellcode:
nicht nur, das ich ein seltsames Ergebnis bei einer fehlenden Initialisierung bekomme, nein, mein Virenscanner hat auch einen Trojaner gefunden:
function Test: string;
begin Result := Result + 'a'; end; for i := 1 to 5 do S := Test; ShowMessage(S); // 'aaaaa' Zitat:
K-H |
AW: Procedure vs Function, Vor- und Nachteile
Zitat:
Dein altes Delphi 7 und dass zuviele böse Programme in Delphi geschrieben wurden und weil viele Virensignaturen einfach nur Schrott sind. ![]() Und die eigene Software kann man als False-Positive melden, dann wird die Signatur meist recht schnell angepasst. ![]() |
AW: Procedure vs Function, Vor- und Nachteile
Zitat:
Bei "Function Test:String;" ist Result ein Zeiger auf eine Stringvariable und da Strings immer initialisiert werden, ist damit auch Result initialisiert. Im nachstehenden Assembler-Auszug kannst du das schön sehen. Vor dem Aufruf der Funktion Test wird mit lea eax,[ebp-$04] die Adresse der lokalen Variablen S in EAX gestellt. Das in [ebp-4] tatsächlich die Variable S gespeichert ist, siehst du 6 Zeilen tiefer, wo S als Parameter für ShowMessage in EAX gestellt wird. Recht hättest du bei z.B. Function Test:Integer;, da ist Result nicht initialisiert. C_Main.pas.5152: for I:=1 to 5 do 0060FFF4 BB05000000 mov ebx,$00000005 C_Main.pas.5153: S:=Test; 0060FFF9 8D45FC lea eax,[ebp-$04] 0060FFFC E8B7FFFFFF call Test C_Main.pas.5152: for I:=1 to 5 do 00610001 4B dec ebx 00610002 75F5 jnz $0060fff9 C_Main.pas.5154: ShowMessage(S); 00610004 8B45FC mov eax,[ebp-$04] 00610007 E8C0A2ECFF call ShowMessage |
AW: Procedure vs Function, Vor- und Nachteile
Unintuitiv ist das Verhalten allerdings schon. Bei einer Funktion in Delphi erwarte ich grundsätzlich temporäre R-Values. Andere Sprachen - wie z.b. C++ - erlauben ja auch die Rückgabe von Referenzen, da ist das Verhalten aber einheitlich.
|
AW: Procedure vs Function, Vor- und Nachteile
Zitat:
Ja, es wird initialisiert, aber eben nicht dort, wo man vermuten könnte (zu Beginn der Funktion), also ist aus Sicht der Funktion dieses Result eben nicht "wirklich" initialisiert, zumindestens nicht unbeding mit 0 (einem Leerstring). |
AW: Procedure vs Function, Vor- und Nachteile
Zitat:
Es ist ein grundsätzliches Konzept von Delphi, dass Strings IMMER initialisiert werden, was ja auch eine Voraussetzung für die Referenzzählung ist. Somit kann es keinen nicht-initialisierten String geben, und auch aus Sicht der Funktion gilt, dass der String (wie auch immer) initialisiert ist und einen gültigen Inhalt hat. Anders wäre es zum Beispiel bei einem Double - da kann auch was ungültiges drin sein. Recht hast du natürlich damit, dass die Funktion nicht davon ausgehen kann, dass Result bei Aufruf der Funktion leer ist. |
AW: Procedure vs Function, Vor- und Nachteile
Zitat:
Delphi-Quellcode:
werden temporäre R-Values verwendet. Wenn man beispielsweise die Addition eines Record überläd, wird ein komplett neuer temporärer Record erstellt und als Ergebnis des Operators zurückgeliefert, welcher dann letztlich der L-Value zugewiesen wird (was meiner Meinung nach schon ziemlicher Schwachsinn ist, aber okay ...). Dadurch dass der String intern als
class operator
Delphi-Quellcode:
Parameter übergeben wird, spart Delphi sich natürlich die unnötige Kopiererei, wird dadurch an dieser Stelle aber extrem inkonsequent. Das erwartete Verhalten wäre, dass beim Betreten der Funktion eine neue lokale String Instanz (
var
Delphi-Quellcode:
) mit einem leeren String initialisiert wird. Auf dieser Instanz kann man dann lokal arbeiten und nach Rückkehr der Funktion wird der Wert dann der entsprechenden left-hand-side zugewiesen. Wäre sicherlich etwas komplizierter die Referenzzählung über Funktionsgrenzen hinweg zu gestalten (Delphi räumt lokale Objekte ja vor dem Verlassen der Funktion frei), aber ist keineswegs ein Ding der Unmöglichkeit. Die hier momentan Verwendete Optimierung ist ein reiner Hack.
Result
|
AW: Procedure vs Function, Vor- und Nachteile
Zitat:
denn wenn dort dieser Result-Record auch als VAR-Parameter in eine neue leere Variable geht, dann wäre es praktisch das Gleiche. |
AW: Procedure vs Function, Vor- und Nachteile
Zitat:
Wenn Result bei jedem Aufruf von "Test" initialisiert wäre, dann würde als Ergebnis immer "a" herhauskommen. Ist aber nicht so. Es ist immer der Wert des vorherigen Result vorhanden. Was für mich erst mal undefiniert ist. Da man ja nicht weis, von wo überall "Test" aufgerufen wird, muss man davon ausgehen, dass Result einen string mit dem Buchstaben "a" in zufälliger Länge hat. Was übrigens irgendwann einen Stackoverflow nach sich zieht, wenn "Test" nur oft genug ausgeführt wird. Zusätzlich kommt hinzu, dass das Verhalten sich mit dem nächsten Compiler ändern kann. Dann wird vielleicht Result bei jedem Aufruf der Funktion auf "" gesetzt. Mann weis ja nie. Es sei denn, dass dieses Verhalten so dokumentiert ist. |
AW: Procedure vs Function, Vor- und Nachteile
Zitat:
Zitat:
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:36 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