Delphi-PRAXiS
Seite 1 von 2  1 2   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Variable ist möglicherweise nicht initialisiert worden (https://www.delphipraxis.net/199597-variable-ist-moeglicherweise-nicht-initialisiert-worden.html)

Codehunter 5. Feb 2019 08:46

Delphi-Version: 10.2 Tokyo

Variable ist möglicherweise nicht initialisiert worden
 
Hallo!

Ich frage mich schon länger, ob die Validierung bzgl. der Warnung "Variable 'foo' ist möglicherweise nicht initialisiert worden" nicht ein überempfindliches Mimöschen ist. Ein Beispiel:
Delphi-Quellcode:
var
  I: Integer;
  LEncoding: TEncoding;
  LEncodings: TStringList;
begin
  LEncodings := TStringList.Create;
  try
    for I := 1 to 6 do begin
      case I of
        1: LEncoding := TEncoding.ANSI;
        2: LEncoding := TEncoding.ASCII;
        3: LEncoding := TEncoding.BigEndianUnicode;
        4: LEncoding := TEncoding.Unicode;
        5: LEncoding := TEncoding.UTF7;
        6: LEncoding := TEncoding.UTF8;
      end;
      LEncodings.AddObject(LEncoding.EncodingName, LEncoding); // <-- Warnung bzgl. "LEncoding"
    end;
    TOpenTextFileDialog(Sender).Encodings.Assign(LEncodings);
  finally
    FreeAndNil(LEncodings);
  end;
end;
Da fällt mir nun wirklich keine Möglichkeit ein, wie "LEncoding" nicht initialisiert sein könnte. Ist der Compiler nicht intelligent genug, die For-Schleife und das den Schleifenzähler bedingende Case in eine Verbindung zu setzen? Oder kann man das in der Konfiguration beeinflussen? Außer natürlich, die Warnung komplett abzuschalten, was ich keinesfalls möchte.

Grüße
Cody

Uwe Raabe 5. Feb 2019 08:52

AW: Variable ist möglicherweise nicht initialisiert worden
 
Zitat:

Zitat von Codehunter (Beitrag 1424707)
Ist der Compiler nicht intelligent genug, die For-Schleife und das den Schleifenzähler bedingende Case in eine Verbindung zu setzen?

Nein, in diesem Fall nicht. Ist ja auch nicht ganz einfach, oder hast du auf Anhieb einen entsprechenden Algorithmus parat?

Würden für die Grenzen der For-Schleife Variablen verwendet, wäre es sogar noch komplizierter. Dann müsste man die Belegung der Variablen analysieren.

Es sollte aber gehen, wenn du in das case einen else-Zweig mit einer Exception einbaust.

Delphi-Quellcode:
      case I of
        1: LEncoding := TEncoding.ANSI;
        2: LEncoding := TEncoding.ASCII;
        3: LEncoding := TEncoding.BigEndianUnicode;
        4: LEncoding := TEncoding.Unicode;
        5: LEncoding := TEncoding.UTF7;
        6: LEncoding := TEncoding.UTF8;
      else
        raise EProgrammerNotFound.Create('WTF?');
      end;

Neutral General 5. Feb 2019 08:54

AW: Variable ist möglicherweise nicht initialisiert worden
 
Naja das ist halt ein sehr sehr spezieller Fall, den man in der Realität selten hat.

Bei Schleifen gibt es oft keine Garantie, dass diese durchlaufen werden, weil die Liste oder das Array was man durchläuft leer sein kann.
Und ein case muss zusätzlich nicht alle Fälle abdecken. Von daher ist eine Variable die nur innerhalb eines case in einer Schleife initialisiert wird und vorher/nachher nicht mehr allgemein eine mögliche Fehlerquelle.
Der Compiler ist in deinem speziellen Fall nicht so schlau, genau zu erkennen, dass du eine statische Schleife hast mit einem case, dass alle möglichen Fälle abdeckt.
Bzw. er ist wahrscheinlich mit Absicht nicht so schlau, weil solche Fälle in "freier Wildbahn" so selten vorkommen, dass es einfacher ist nur grob drüber zu gucken, als jedes Konstrukt bis ins tiefste zu analysieren für die 0,1% der Fälle wo kein Problem auftreten kann.

Codehunter 5. Feb 2019 09:21

AW: Variable ist möglicherweise nicht initialisiert worden
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1424708)
Nein, in diesem Fall nicht. Ist ja auch nicht ganz einfach, oder hast du auf Anhieb einen entsprechenden Algorithmus parat?

Ich bin nur für das Aufstöbern solcher Glitches und das Meckern zuständig ;-) Also zumindest was meine Quellen angeht habe ich den Fall gar nicht so selten. Eigentlich bin ich ja dankbar für die Warnung. Nur in Fällen wie diesen muss ich ein eigentlich überflüssiges ELSE in das CASE einbauen und dazu noch einen Kommentar, damit ich in drölfzig Jahren auch noch weiß, warum.

Uwe Raabe 5. Feb 2019 09:33

AW: Variable ist möglicherweise nicht initialisiert worden
 
Zitat:

Zitat von Codehunter (Beitrag 1424713)
Nur in Fällen wie diesen muss ich ein eigentlich überflüssiges ELSE in das CASE einbauen

Ein ELSE ist niemals überflüssig - eher das Ergebnis jahrelanger Erfahrung.

Schokohase 5. Feb 2019 09:36

AW: Variable ist möglicherweise nicht initialisiert worden
 
Das Else ist nicht überflüssig, denn es ist ein Schutz, falls mal jemand auf die dusselige Idee kommt und einen Case entfernt. Ohne Else bekommst du eine Warnung und mit Else gibt es eine Exception wenn nicht alle Fälle behandelt wurden.

Das ist ein Feature.

p80286 5. Feb 2019 10:40

AW: Variable ist möglicherweise nicht initialisiert worden
 
Da war der schokohase schneller. Das else sollte immer dabei sein. Genauso wie ich immer eine Basisinitialisierung vornehme:
Delphi-Quellcode:
begin
  max:=cMax;
  if a>20 then max:=50
  else max:=100;
........
Ist eigentlich überflüssig, aber sicher.

Gruß
K-H

Codehunter 5. Feb 2019 10:48

AW: Variable ist möglicherweise nicht initialisiert worden
 
Und das nachdem man jahr(zehnt)elang geübt hat, möglichst schlanken und übersichtlichen Code zu schreiben ^^

Schokohase 5. Feb 2019 11:18

AW: Variable ist möglicherweise nicht initialisiert worden
 
Zitat:

Zitat von Codehunter (Beitrag 1424726)
Und das nachdem man jahr(zehnt)elang geübt hat, möglichst schlanken und übersichtlichen Code zu schreiben ^^

Ich will dir ja den Tag nicht verderben, aber das ist auf jeden Fall schlanker.
Wegen der Übersichtlichkeit (und im Hinblick auf Geschwindigkeit) würde ich das ganze sogar noch ganz anders angehen.
Delphi-Quellcode:
var
  LEncodings: TStringList;
  lEncoding: TEncoding;
begin
  LEncodings := TStringList.Create;
  try
    for lEncoding in TArray<TEncoding>.Create(TEncoding.ANSI, TEncoding.ASCII, TEncoding.BigEndianUnicode, TEncoding.Unicode, TEncoding.UTF7, TEncoding.UTF8) do
      LEncodings.AddObject(lEncoding.EncodingName, lEncoding);

    TOpenTextFileDialog(Sender).Encodings.Assign(LEncodings);

  finally
    LEncodings.Free();
  end;
end;

p80286 5. Feb 2019 11:44

AW: Variable ist möglicherweise nicht initialisiert worden
 
Nichts für ungut, das erinnert mich an diesen Einzeilercode, den es vor 30 Jahren in jeder Computerfachzeitschrift gab. Die erste Version scheint mir wesentlich übersichtlicher.

Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:48 Uhr.
Seite 1 von 2  1 2   

Powered by vBulletin® Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2019 by Daniel R. Wolf