Delphi-PRAXiS
Seite 2 von 5     12 34     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Übergebenes nil erkennen? (https://www.delphipraxis.net/167926-uebergebenes-nil-erkennen.html)

sx2008 26. Apr 2012 00:12

AW: Übergebenes nil erkennen?
 
Zitat:

Zitat von MaBuSE (Beitrag 1163577)
Wo steht das denn in der Doku?

Etwas versteckt, hier:
http://docwiki.embarcadero.com/Libra...t.InitInstance
Setzt alle Speicherzellen in dem für ein neues Objekt reservierten Bereich auf Null und initialisiert den Zeiger auf die Tabelle der virtuellen Methoden der Instanz.

himitsu 26. Apr 2012 00:33

AW: Übergebenes nil erkennen?
 
Zitat:

Zitat von MaBuSE (Beitrag 1163577)
Wenn es dokumentiert ist, ist das was anderes.
Meines Wissens ist es nur für Strings doumentiert.

[edit]Undokumentiere Dinge, die man "nur" durch ausprobieren weiss, können sich ja jederzeit bei einem Versionswechsel ändern.[/edit]

Wo steht das denn in der Doku?

Windows initialisiert Speicher mit 0, wenn man den bei ihm reserviert, somit sind die globalen Variablen auch initialisiert.
Und beim Erstellen von Objekten wird definitiv ein Delphi-Referenz durchsuchenFillChar mit 0 über den Instanzspeicher gejagt.
Zitat:

Zitat von MSDN: VirtualAlloc
Reserves or commits a region of pages in the virtual address space of the calling process. Memory allocated by this function is automatically initialized to zero, unless MEM_RESET is specified.

Zitat:

Zitat von OH: TObject.InitInstance
Setzt alle Speicherzellen in dem für ein neues Objekt reservierten Bereich auf Null und initialisiert den Zeiger auf die Tabelle der virtuellen Methoden der Instanz.

Und ansonsten werden auch Strings (ausgenommen der ShortString), dynamische Arrays, Interfaces und Variants immer initialisiert.
Das gilt aber nur die Variablen selber und nicht den Inhalt der Arrays oder Strings ... diese sind wie lokale Variablen, also uninitialisiert, bis auf die genannten Sonderfälle.

Bummi 26. Apr 2012 06:09

AW: Übergebenes nil erkennen?
 
@Mabuse
Delphi-Quellcode:
var
 T:Tbutton;
begin
  t := nil;
  Showmessage(IntToHex(Integer(t),8));
end;

Medium 26. Apr 2012 08:06

AW: Übergebenes nil erkennen?
 
0 <> nil (bzw. NULL) gilt nur semantisch, und ist meist in Datenbanken auch so umgesetzt, wie auch in einigen wenigen Sprachen. In Delphi (und auch C) wird für die Darstellung von nil/NULL der numerische Wert 0 genommen, da er wenn dereferenziert in ungültigen Speicher zeigt, und somit niemals für eine gültige Referenz stehen kann (zumindest in Sprachen, in denen Referenz = Zeiger auf Speicher ist). Theoretisch ist also tatsächlich 0 <> nil, aus praktischen Gründen gilt in Delphi aber doch 0 = nil.

himitsu 26. Apr 2012 08:53

AW: Übergebenes nil erkennen?
 
Wobei Delphi auch hart typsicher unterscheidet.

Du kannst einen Pointer nicht auf 0 setzen oder einen Integer auf nil.
Für den Variant gibt es den Wert NULL (auch als Konstante) und wenn man dem Variant eine 0 zuweist, dann ist was was Anders.

Daß intern, also die Daten im RAM, der Integer (eigentlich aber richtiger Cardinal) NativeUInt den selben Wert aufweisen, das ist soweit richtig.
Dennnoch
Delphi-Quellcode:
nil <> 0
Cardinal(nil)  = 0  // nur für 32 Bit, da ein paar Idioten meinten Integer/Cardinal einfrieren zu müssen
NativeUInt(nil) = 0

Medium 26. Apr 2012 10:26

AW: Übergebenes nil erkennen?
 
Stimmt, ohne Casts ist Delphi an sich da auch "sauber". Gar nicht mehr im Hinterstübchen gehabt =) Ebenso die Variants - viel zu selten Benutzt bei mir, aber ich erinnere mich: Das müsste das OLE_NULL sein gell? Dann ist bei denen sogar wie in Datenbanken die Unterscheidung von NULL und 0 noch deutlicher und nicht so einfach via Cast überführbar. Danke fürs zurechtrücken!

Für die Initialisierung von Feldern gilt aber dennoch, weil FillChar da ja ohne Typprüfung drüberjodelt, initialisiert mit 0 -> Referenzen gelten als nil.

himitsu 26. Apr 2012 10:59

AW: Übergebenes nil erkennen?
 
Wurde z.B. in einem Record etwas eingetragen und du willst es dennoch "sicher" nullen, dann

Delphi-Quellcode:
var
  R: record
    ..
  end;

Finalize(R);
FillChar(R, SizeOf(R), 0);
Alternativ kann man etwas manuell initialisieren, wenn es von Delphi noch nicht automatisch initialisiert wurde
Delphi-Referenz durchsuchenInitialize
Delphi-Referenz durchsuchenFinalize

Stevie 26. Apr 2012 17:44

AW: Übergebenes nil erkennen?
 
Schonmal aufgefallen, dass ne AV mit der Meldung "Read of address 00000000'." in den meisten Fällen auf einen nil Pointer hinweist?

solus 26. Apr 2012 19:49

AW: Übergebenes nil erkennen?
 
Whoa, was sich doch nicht alles aus einer einfachen Frage ergibt.

Der konkrete Anwendungsfall (über das Minimalbeispiel hinaus) war die Erstellung eines Binären Suchbaums (AVL).

type TKnoten=class(TObject)

rechts,links : TKnoten
...
end;

function hoehe(knoten:TKnoten) : integer;
begin
if knoten =nil then result:=0
else ...
end;

function balance(knoten : TKnoten) : integer;
begin
result:=hoehe(links)-hoehe(rechts);
end;

Das Warnsystem hat bei mir daher nicht angeschlagen (rechts,links werden ja benutzt) und Objektfelder werden anscheinend wie lokale Variablen behandelt.

Mittels

constructor create; override;
begin
inherited create;
rechts:=nil;
links:=nil;
end;

sollte ich dann aber sicher sein, oder?

Einzige Alternative wäre halt ne blöde Fallunterscheidung...

Medium 26. Apr 2012 20:41

AW: Übergebenes nil erkennen?
 
Hast du bei deinen Methoden einfach nur das "TKnoten." vergessen, oder sind das wirklich nur Funktionen/Prozeduren (gegenüber Methoden (welche immer zu einer Klasse gehören))? In dem Fall würden die Felder nicht wie lokale Variablen behandelt, sondern Delphi setzt innerhalb von Methoden der Klasse vor die eigenen Felder implizit eine "self." Referenz. Es sind aber nach wie vor Felder, keine lokalen Variablen. Es muss daher, dem Beispiel hier nach, auch ohne explizites nil im Konstruktor gehen (welche man übrigend nicht überläd).

Ich vermute schon fast einen Klassiker hier:
Delphi-Quellcode:
var
  k: TKnoten;
begin
  // Erzeugung vergessen
  k.TuWas();
  .
  .
end;
Also Fehler in der Verwendung, nicht der Klasse selbst. Gegebenenfalls kann das auch innerhalb einer Methode von TKnoten passieren, wenn es dort solche gibt, die neue Knoten einfügen und diese selbst erzeugen müssten (also keinen fertigen neuen TKnoten als Parameter von aussen mit bekommen).


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:19 Uhr.
Seite 2 von 5     12 34     Letzte »    

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