ich hoffe Ihr seid alle gut ins neue Jahr gestartet!
Obwohl ich ja schon sehr lange in Pascal, Delphi und nun Lazarus programmiere habe ich doch eine ziemlich grundsätzliche Frage, die mich in einem aktuellen Projekt ziemlich stört und vielleicht gibt es dafür eine schöne Lösung, auf die ich bisher nicht gestoßen bin.
Ich verwende die Format-Funktion sehr intensiv für das Logging einer Konsolen-Anwendung die im Hintergrund regelmäßig aufgerufen wird um ihren Dienst zu tun. Da niemand zuschaut was das Programm macht ist es sehr wichtig, dass die Log-Datei alles Relevante enthält um Probleme nachzuvollziehen und sie zu korrigieren.
Insgesamt ist Free-Pascal ja sehr schön darin viele Fehler in der Compilerzeit abzufangen. So sorge ich dafür, dass es wirklich zu keinen Meldungen oder Warnings kommt.
Aber leider macht mir die Format-Funktion da einen gewaltigen Strich durch die Rechnung.
Beispiel
Code: Alles auswählen
function EineFunktion(out a : Integer; out b : String) : Boolean;
begin
a := Random(5000);
b := 'Ein String';
Result := (a<>123);
end;
procedure MachEinenFehler;
var
a : Integer = 0;
b : String = '';
begin
if not EineFunktion(a,b) then
LogThis(Format('Es ist ein Fehler (%d) bei der Bearbeitung von "%s" aufgetreten!',[a,b]));
end;Die Funktion liefert nur sehr selten False zurück, so gelangt die Meldung kaum ins Log und debuggen kan man das auch nicht wirklich. (Ja man könnte manuell die Bedingung if not EineFunktion(a,b) then in if TRUE or not EineFunktion(a,b) then ändern, aber das ist in einem Programm mit sehr vielen Verzweigungen und den daraus resultierenden "Vielleichts" recht komplex.
Aber das Obige Programm würde ja funktioneren und tun was es soll.
Jetzt kommt aber ein unbedarfter Programmierer (ich!) auf die Idee die EineFunktion wie folgt zu ändern
Code: Alles auswählen
{Der Typ des Parameters a wurde von Integer in String geändert!}
function EineFunktion(out a : String; out b : String) : Boolean;
var
r : Integer;
begin
r := Random(5000);
a := IntToStr(r);
b := 'Ein String';
Result := (r<>123);
end;eintest.pas(50,24) Error: Call by var for arg no. 1 has to match exactly: Got "LongInt" expected "AnsiString"
Er meint zu Recht, dass in der Zeile
if not EineFunktion(a,b) then
der Parameter a nicht vom Typ String sei.
Also ändert man schnell
Code: Alles auswählen
procedure MachEinenFehler;
var
a : String = ''; // War Integer
b : String = '';
begin
if not EineFunktion(a,b) then
LogThis(Format('Es ist ein Fehler (%d) bei der Bearbeitung von "%s" aufgetreten!',[a,b]));
end;Das Programm rennt auch schön, aber in einem unbeaufsichtigten Moment kommt es zu einer Exception bei der Ausführung von Format.
"Invalid argument index in format "'Es ist ein Fehler (%d) bei der Bearbeitung von "%s" aufgetreten!".
Das Programm findet zu Recht, dass das "%d" nicht zum ersten Parameter passen will.
Und das ist aus mehreren Gründen sehr böse:
1.) Geht die Information verloren, die für den Fehler gesorgt und ursächlich für den Aufruf war.
2.) Schlägt die Exception bis irgendwohin durch, wo man tatsächlich nicht damit gerechnet hat.
Also was kann man da tun?
Gibt es irgendeine schlaue Methode diese Format-Strings wenigstens zur Laufzeit durchzutesten um so beim Starten (oder wenigstens in einer Debug-Funktion) diese Fehler zu finden?
Wie macht ihr das?
Liebe Grüße aus Hildesheim
Ekkehard