Hier können jetzt diverse Probleme auftreten.
Wenn man die zwei Free-Anweisungen jetzt in einen Finally-Block setzt - ohne sonstige Fehlerbehandlung - findest Du weder den Fehler besser noch ist Dein Datenbestand besser geschützt noch erhält der Anwender bessere Fehlerinformationen.
Nur der Speicherplatz der zwei Objekte wird wieder freigegeben. Der Aufrufer der Prozedur Überweisung weiß nichts von dem Fehler und das Programm geht davon aus, dass alles passt.
Doch, denn es geht ja um den Fall, dass eine
Exception ausgelöst wird, so dass die Freigabe des Objekts übersprungen würde, weil man bei der
Exception heraus springt. Dann kann die
Exception zwar abgefangen werden, aber der Speicher wird nicht freigegeben.
Und nun nehmen wir mal an der Code wird in einem Programm immer wieder aufgerufen, das länger läuft, z.B. ein Webservice... da ist dann irgendwann trotz sauberer Behandlung der Exceptions der Speicher voll.
Wenn es nur um wenige Aufrufe geht, merkt man in der Tat nicht viel davon. Aber das Programm benutzt eben mehr Speicher als nötig.
Noch schlechter wird es, wenn man in dem Objekt ein
Handle auf eine Datei offen hat oder ähnliches, so dass die Datei dann gesperrt bleibt bis das Programm beendet wird.
Und damit man das nicht immer neu bewerten muss, macht es Sinn einfach immer eine korrekte Behandlung solcher potentiellen Probleme einzubauen. Denn sonst müsstest du ja bei jeder Änderung schauen, ob deine Prozedur nicht irgendwo aufgerufen wird, wo dann eine Behandlung nötig wird...
Davon abgesehen bringt ein Ressourcenschutzblock nur etwas, wenn er auch korrekt aufgebaut ist (Konstruktoraufruf vor dem try, sonst springt man bei einer
Exception im Konstruktor auch in das finally obwohl die Variable noch gar nicht zugewiesen ist und dann knallt es ggf. dort erneut):
Delphi-Quellcode:
procedure Run;
begin
obj1 := TObject.Create;
try
Beep;
obj2 := TObject.Create;
try
obj3 := TObject.Create;
try
Beep;
finally
obj3.Free;
end;
finally
obj2.Free;
end;
finally
obj1.Free;
end;
end;
try
Run;
except
on E:
Exception do
begin
WriteLog(E);
UserDialog(Format('
Interner Fehler: %s - %s', [E.ClassName, E.
Message]));
end;
end;