Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - mehrere Optionale Parameter - Fehler
Tranx - Mo 28.01.13 07:34
Titel: mehrere Optionale Parameter - Fehler
Hallo, ich habe (Delphi 5) einen folgenden Prozedur definiert:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure Procname(a : string; b : string = ''; c : integer = 10); begin : if c<10 then TueIrgendwas else TueWasAnderes; : end; |
Wenn ich nun den Aufruf Procname('Test') mache, dann bekomme ich zwar a als 'Test', b als '' aber c nicht unbedingt als 10 übergeben. Manchmal steht da 0, dann -1 in c. Dann ist eine Abfrage innerhalb der Prozedur nicht möglich, denn das Ergebnis ist nicht eindeutig (siehe Teil der Prozedur)
Wenn ich die Funktion so definiere:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure Procname(a : string; c : integer = 10); begin : if c<10 then TueIrgendwas else TueWasAnderes; : end; |
Dann hat c immer 10, wenn ich nur den Aufruf Procname('Test') wähle.
Stört der eine optionale Parameter den anderen? Ich habe nun die zweite Prozedurdeklaration gewählt, damit es klappt. Aber so recht verstehe ich den Effekt nicht. Die Parameter als const-Paramter zu definieren bringt nichts, gleicher Effekt.
Hat irgendwer einen Gedanken, wieso das so ist?
WasWeißDennIch - Mo 28.01.13 08:52
Hast Du evtl. noch versehentlich eine lokale Variable gleichen Namens deklariert? Unter Delphi 7 (ältere Versionen habe ich nicht installiert) kann ich das Verhalten jedenfalls nicht nachvollziehen.
Tranx - Mo 28.01.13 13:04
Ich habe bei dem Programm (die Parameter sind nur Beispiel) eine strikte Trennung zwischen lokalen/globalen Variablen und Parametern vorgenommen.
Lokale Variablen beginnen mit einem kleinen l, gefolgt von einem Kleinbuchstaben, aus dem ich die Art der Variablen erkenne: z.B. i für Ganzzahl, e für Float, o für Object, s für String ...
Globale Variablen habe ich wie folgt gekennzeichnet: beginnendes kleines g und dann kleine Kennzeuchnung wie lokale Variable.
Parameter fangen mit einem kleinen p an.
Also sieht der Prozeduraufruf beispielhaft wie folgt aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure ProcName(psText : string; psZusatz : string = ''; piTyp : integer = 10); var lsTest : String; liVar1 : Integer; begin lsTest := psText + #10#13; if piTyp<10 then TueIrgendwas(lsTest); else TueWasAnderes(lsTest); end; |
So ist eine Verwechslung nicht möglich. Sieht zwar nicht wirklich toll aus, aber ich kann viel einfacher über mehrere Quelltexte bestimmte Größen in ihrem Namen ändern und auch viel einfacher Variablen von Parametern und Funktionsaufrufen unterscheiden. Funktionen/Prozeduren beginnen mit einem Großbuchstaben.
Auch kann ich sofort den Typ der Variablen und Parameter erkennen, was bei Namen wie : Value, Wert, Inhalt ... nicht möglich ist.
folgende Typzeichen habe ich belegt:
a: Array mit anschließendem Typ der Variable (ae = z.B. Array[1..12] of double)
b: boolean
c: char
e: extended, double, single ...
f: procedure/function
i: integer, byte, word, dword, longint
m: Set (Menge) z.B. Set of Char;
o: Objekt/Klasse (z.B. TList, TObject, TButton....)
p: Pointer
r: record
s: string
t: TDateTime
v: Variant
Einzig Variablen wie i, s, n habe ich nicht geändert, nur konsequenterweise klein geschrieben. Auch die Parameter Sender, Value (bei Property) und andere vordeklarierte Parameter von Delphi habe ich nicht geändert, selbstverständlich auch nicht Self!
So kann ich jetzt auch Delete oder Text verwenden, eben mit den vorgenannten Buchstaben: z.B. lbDelete, lsText, psText ...
Wahrscheinlich, muss mal sehen, werde ich auch Records entsprechend ausstatten (mit vorangestelltem r) Dann sieht man sofort, was Record-Eigenschaften sind. Oder auch Klassenvariablen (vorangestelltes f).
z.B.
Delphi-Quelltext
1: 2: 3: 4: 5:
| type grTest = record rsEintrag : string; rbGelesen : boolean; end; |
Da keine Verwechslung vorliegt ist der Effekt eben immer noch nicht klar. Aber es funktioniert mit einem optionalen Paramter.
WasWeißDennIch - Mo 28.01.13 13:13
Wie gesagt, unter Delphi 7 funktioniert es auch mit 2 optionalen Parametern. Wenn Verwechslungen wirklich zu 100% auszuschließen sind, scheint es sich tatsächlich um einen Delphi-Bug zu handeln. Das sollte aber jemand mit Delphi 5 verifizieren.
Marc. - Mo 28.01.13 13:35
Unter Delphi2009 ist der Bug auch nicht zu beobachten.
Das ist nun von meiner Seite einfach mal ins Blaue geschossen:
Wie sieht denn der erzeugte Code aus? Scheinbar werden ja die Parameter falsch übergeben. :gruebel:
Dazu am besten mal ein neues Projekt nur mit dem relevanten Code anlegen, sowie im ersten Beitrag. Dann einen Breakpoint auf die aufzurufende Funktion setzen und mit Strg+Alt+C einmal in den Assembler-Code und Stack schauen.
Das sollte dann, wenn alles korrekt ist, in etwa so aussehen:
Delphi-Quelltext
1: 2: 3: 4: 5:
| Unit1.pas.36: Procname('Test'); 0046CD0C B90A000000 mov ecx,$0000000a 0046CD11 33D2 xor edx,edx 0046CD13 B82CCD4600 mov eax,$0046cd2c 0046CD18 E877FFFFFF call Procname |
Die Parameter-Werte werden den Registern direkt übergeben.
Anschließend mal durchsteppen und schauen, ob bereits vor oder erst in der Procname-Funktion das entsprechende Register irgendwo überschrieben wird. :?
Der Problem erinnert ein wenig an diesen
Bug [
http://buglist.jrsoftware.org/generated/entry0539.htm], auch wenn hier keine Overload-Direktiven dabei sind. :nixweiss:
Schöne Grüße
Tranx - Mo 28.01.13 15:05
Ich habe es mal mit einer leeren Anwendung probiert. Da klappt es. Scheint doch irgendwo in meinem Programm eine Wechselwirkung zu existieren. Das hatte ich mit anderen Dingen hier udn da mal, z.B. wenn ich die Komponenten TFBook eingebunden hatte, gab es unkontrolliert Probleme mit z.B. TQuery-Komponenten, die dann unerklärlicherweise nicht auf active gesetzt werden konnte. Wenn ich dann nur die TFBook-Komponenten aus dem Programm nahm, funktionierte wieder alles.
Auf jeden Fall danke für die Hinweise. Werde mal die Registerbelegung genauer untersuchen.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!