jaenicke hat folgendes geschrieben : |
Wenn aber in AddFontMemResourceEx eine Exception auftritt, wird bei deinem Quelltext rs nie freigegeben. Und deshalb waren die try..finally Blöcke sinnvoll... |
Das passiert wie gesagt nicht. AddFontMemResourceEx wirft keine Exceptions zum Aufrufer, auch wenn man total falsche Parameter übergibt. Aber wenn man paranoid ist, kann man natürlich das "rs.Free" in einen eigenen finally-Block machen, oder in den vorhandenen zu FreeLibrary - dann muss man natürlich rs vor dem ersten try-Block mit nil initialisieren.
Das hier...
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| procedure LadeRes1; var r1, r2, r3: TResourceStream; begin r1 := TResourceStream.Create(HInstance, 'resource1', RT_RCDATA); try r2 := TResourceStream.Create(HInstance, 'resource2', RT_RCDATA); try r3 := TResourceStream.Create(HInstance, 'resource3', RT_RCDATA); try finally r3.Free; end; finally r2.Free; end; finally r1.Free; end; end; |
... ist gleichwertig mit dem hier ...
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| procedure LadeRes2; var r1, r2, r3: TResourceStream; begin r1 := nil; r2 := nil; r3 := nil; try r1 := TResourceStream.Create(HInstance, 'resource1', RT_RCDATA); r2 := TResourceStream.Create(HInstance, 'resource2', RT_RCDATA); r3 := TResourceStream.Create(HInstance, 'resource3', RT_RCDATA); finally r3.Free; r2.Free; r1.Free; end; end; |
... wobei ich die zweite Variante für besser lesbar halte.
Der erzeugte Code ist nicht identisch; jedes einzelne "try" produziert Code, der auf dem Stack einen neuen Structured Exception Handling (SEH) Frame erzeugt.
Aber der Endeffekt ist derselbe, die Objekte werden in jedem Fall freigegeben. Die Initialisierung mit nil ist wichtig, da lokale Variablen anfangs "zufällige" Werte enthalten. Nur die Typen mit Compiler Magic (Strings, dynamische Arrays, Interfaces) werden automatisch initialisiert.