![]() |
Delphi-Version: XE2
Warum macht es nichts, bei Rückgabe eines Interfaces nichts initialisiert zu haben?
Ich brauchte eine Weile um zu merken, dass der Delphi-Compiler mich nicht warnt, wenn ich in einer Funktion den Rückgabewert nicht definiere und dieser ein Interface ist.
Warum ist das so?
Delphi-Quellcode:
Der Compiler warnt nur
unit Unit1;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs; type IInterface = interface ['{3E4EDB7F-A266-48DE-8415-F73406A38C7C}'] end; TForm1 = class(TForm) function testFunc(): IInterface; function testFunc2(): TForm1; procedure FormCreate(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin if testFunc() = nil then ShowMessage('nil'); if testFunc2() = nil then ShowMessage('nil'); end; function TForm1.testFunc: IInterface; begin // end; function TForm1.testFunc2: TForm1; begin // end; end.
Code:
Bein Ausführen bekomme ich sowohl
[DCC Warnung] Unit1.pas(41): W1035 Rückgabewert der Funktion 'TForm1.testFunc2' könnte undefiniert sein
Code:
als auch
'nil interface'
Code:
. Vor allem dass testFunc2() nil zurückgibt wundert mich. Ich hätte gedacht, es ist in der Funktion ein normaler Zeiger auf dem Stack der erst einmal nicht initialisiert wurde und dort erst einmal irgendetwas steht?
'nil class'
|
AW: Warum macht es nichts, bei Rückgabe eines Interfaces nichts initialisiert zu habe
1) Ein Interface wird implizit immer mit nil initialisiert.
2) Bei der Rückgabe einer Klasseninstanz kommt wirklich irgendetwas zufälliges raus - in diesem Fall war es offenbar nil. |
AW: Warum macht es nichts, bei Rückgabe eines Interfaces nichts initialisiert zu habe
Ich habe gerade erneut mindestens eine Halbe Stunde damit verbraten, mich hiervon wieder durcheinander bringen zu lassen.
Gibt es irgendeine Möglichkeit, dass der Compiler mich warnt wenn ich folgendes tue:
Delphi-Quellcode:
Ich komme partout damit nicht zurecht und das passiert mir alle paar Monate immer wieder. :wall:
function someFunc(): IInterface;
begin // Nichts end; |
AW: Warum macht es nichts, bei Rückgabe eines Interfaces nichts initialisiert zu habe
Zitat:
Interface-Variablen sind ja, wie schon genannt, immer initialisiert, also gibt es da nichts zu meckern, weil es das ja schon ist. Auch wenn das mit dem Result leider ein Sonderfall ist, denn was wird nicht in der Funktion initialisiert, sondern beim Aufrufer. (das Result wird hier, bei diesen Typen, in einen VAR-Parameter umgewandelt) > dyn. Array, String, Interface und Variant Und es macht Spaß, wenn die Funktion in einer Schleife aufgerufen wird.
Delphi-Quellcode:
function Mist: string;
begin Result := Result + 'a'; end; for i := 1 to 5 do S := Mist; // oder S := S + Mist; ShowMessage(S); |
AW: Warum macht es nichts, bei Rückgabe eines Interfaces nichts initialisiert zu habe
Eine Warnung in solch einem Fall wäre mehr wert als so manche Warnings, die der Compiler ausspuckt :(
Leider aufgrund der schon erwähnten Architektur nicht möglich ohne bei potenziell korrektem Code Warnings zu produzieren. Denn das hier kann je nach Aufruf funktionieren (was nicht heißt, dass das guter Code ist):
Delphi-Quellcode:
:shock:
function Foo: IFoo;
begin Result.Bar; end; |
AW: Warum macht es nichts, bei Rückgabe eines Interfaces nichts initialisiert zu habe
Eigentlich müsste die Prüffunktion dafür, beim Result, einfach nur zu Funktionsbeginn "vergessen" daß die Variable schon initisialisert ist.
Also einfach den VAR-Parameter wie einen OUT-Parameter behandeln, wenn es mal ein Result war. Aber ob man es nach 15 Jahren schafft das jetzt noch zu reparieren? |
AW: Warum macht es nichts, bei Rückgabe eines Interfaces nichts initialisiert zu habe
Zitat:
Zitat:
Zitat:
Zitat:
Der Grund war Code, der das dynamische Rückgabe-Array nicht abgelöscht und es fleißig mit "SetLength(Result, Length(Result) + 1)" in einer Schleife vergrößert hat (man hätte ja auch die Anzahl vorher bestimmen können). Pseudocode:
Delphi-Quellcode:
begin
for I := 0 to Items.Count - 1 do begin FMyArrayObjectField := Items[I].ToArray; ... end; end. function TMyItem.ToArray: TArray<string>; begin // hier das fehlende "Result := nil;" for I := 0 to Item.ChildCount - 1 do begin SetLength(Result, Length(Result) + 1); Result[High(Result)] := Item.Childs[I]; end; end; |
AW: Warum macht es nichts, bei Rückgabe eines Interfaces nichts initialisiert zu habe
Zitat:
|
AW: Warum macht es nichts, bei Rückgabe eines Interfaces nichts initialisiert zu habe
Zitat:
- Inplace-Reallocation bei mittleren und großen Blöcken ... wenn dahinter noch Platz ist, wird das einfach angehängt - und beim Reallocationen wird nicht nur das angeforderte angepasst ... wird ich Schritten erledigt, so daß die nächsten Reallocationen schon genügend Platz haben Zitat:
Drum funktioniert das oftmals "zufälliger" Weise, aber in Schleifen aufgerufen, hat man dann seinen Spaß. Es ist wirklich zu schade, daß hier die Prüfung "Variable nicht initialisiert" nicht greift. :cry: Bin auch schonmal in diese Falle getreten. Der Pseudocode von jbg sieht intern praktisch so aus. So erkennt man dann auch ganz schnell, warum das schief gehen muß. Und bei einmaligem/erstmaligem Ausführen, passt es ja zufällig noch.
Delphi-Quellcode:
Und aus dem
procedure TMyItem.ToArray(var Result: TArray<string>);
begin // aber hier wird es eben nicht "nochmal" initialisiert for I := 0 to Item.ChildCount - 1 do begin SetLength(Result, Length(Result) + 1); Result[High(Result)] := Item.Childs[I]; end; end; var FMyArrayObjectField: TArray<string>; begin // FMyArrayObjectField wurde quasi in diesem Begin initialisiert for I := 0 to Items.Count - 1 do begin Items[I].ToArray(FMyArrayObjectField); ... end; end;
Delphi-Quellcode:
wird das
begin
for I := 0 to Items.Count - 1 do begin Items[I].ToArray; // ohne Zuweisung ... EinProperty := Items[I].ToArray; end; end;
Delphi-Quellcode:
var
GeheimeTempVar: TArray<string>: begin for I := 0 to Items.Count - 1 do begin Items[I].ToArray(GeheimeTempVar); ... Items[I].ToArray(GeheimeTempVar); SetterDes_EinProperty(GeheimeTempVar); end; end; |
AW: Warum macht es nichts, bei Rückgabe eines Interfaces nichts initialisiert zu habe
Zitat:
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:37 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 by Thomas Breitkreuz