Embarcadero Delphi
Utilisation de try, sauf et enfin
Recherche…
Syntaxe
Try-except: try [instructions] sauf [[[sur E: ExceptionType]]] [else instruction] | [déclarations] se terminent;
Try-finally: try [statements] finally [instructions] end;
Simple try..finally exemple pour éviter les fuites de mémoire
Utilisez try
- finally
pour éviter les fuites de ressources (telles que la mémoire) en cas d'exception lors de l'exécution.
La procédure ci-dessous enregistre une chaîne dans un fichier et empêche la TStringList
de TStringList
.
procedure SaveStringToFile(const aFilename: TFilename; const aString: string);
var
SL: TStringList;
begin
SL := TStringList.Create; // call outside the try
try
SL.Text := aString;
SL.SaveToFile(aFilename);
finally
SL.Free // will be called no matter what happens above
end;
end;
Qu'une exception se produise lors de la sauvegarde du fichier, SL
sera libéré. Toute exception ira à l'appelant.
Retour d'exception-sécurité d'un nouvel objet
Lorsqu'une fonction retourne un objet (par opposition à l' utilisation d' un objet transmis par l'appelant), faites attention qu'une exception ne provoque pas de fuite de l'objet.
function MakeStrings: TStrings;
begin
// Create a new object before entering the try-block.
Result := TStringList.Create;
try
// Execute code that uses the new object and prepares it for the caller.
Result.Add('One');
MightThrow;
except
// If execution reaches this point, then an exception has occurred. We cannot
// know how to handle all possible exceptions, so we merely clean up the resources
// allocated by this function and then re-raise the exception so the caller can
// choose what to do with it.
Result.Free;
raise;
end;
// If execution reaches this point, then no exception has occurred, so the
// function will return Result normally.
end;
Les programmeurs naïfs peuvent tenter d'attraper tous les types d'exception et renvoyer nil
partir d'une telle fonction, mais ce n'est là qu'un cas particulier de la pratique générale découragée d'attraper tous les types d'exception sans les manipuler.
Essayez-enfin imbriqué dans try-except
Un bloc try
- finally
peut être imbriqué dans un bloc try
- except
.
try
AcquireResources;
try
UseResource;
finally
ReleaseResource;
end;
except
on E: EResourceUsageError do begin
HandleResourceErrors;
end;
end;
Si une exception se produit dans UseResource
, l'exécution passera à ReleaseResource
. Si l'exception est une EResourceUsageError
, l'exécution passe alors au gestionnaire d'exceptions et appelle HandleResourceErrors
. Les exceptions de tout autre type ignoreront le gestionnaire d'exceptions ci-dessus et remonteront jusqu'au prochain try
- except
bloquer la pile d'appels.
Les exceptions à AcquireResource
ou ReleaseResource
entraînera l' exécution d'aller au gestionnaire d'exception, sauter le finally
bloc, soit parce que le correspondant try
bloc n'a pas encore été entré ou parce que le finally
bloc a déjà été saisi.
Essayez, sauf imbriqué dans try-finally
Un bloc try
- except
peut être imbriqué dans un bloc try
- finally
.
AcquireResource;
try
UseResource1;
try
UseResource2;
except
on E: EResourceUsageError do begin
HandleResourceErrors;
end;
end;
UseResource3;
finally
ReleaseResource;
end;
Si une EResourceUsageError
se produit dans UseResource2
, l'exécution passe alors au gestionnaire d'exceptions et appelle HandleResourceError
. L'exception sera considérée comme gérée, donc l'exécution continuera à UseResource3
, puis ReleaseResource
.
Si une exception d'un autre type se produit dans UseResource2
, alors le gestionnaire d'exception UseResource2
ici ne s'appliquera pas, l'exécution passera par-dessus l'appel UseResource3
et ira directement au bloc finally
, où ReleaseResource
sera appelé. Après cela, l'exécution passera au gestionnaire d'exceptions suivant lors de la création de l'exception.
Si une exception se produit dans un autre appel dans l'exemple ci-dessus, HandleResourceErrors
ne sera pas appelé. En effet, aucun des autres appels ne se produit dans le bloc try
correspondant à ce gestionnaire d'exceptions.
Essayez-enfin avec 2 objets ou plus
Object1 := nil;
Object2 := nil;
try
Object1 := TMyObject.Create;
Object2 := TMyObject.Create;
finally
Object1.Free;
Object2.Free;
end;
Si vous n'initialisez pas les objets avec nil
dehors du bloc try-finally
, si l'un d'eux ne peut pas être créé, un AV se produira sur le bloc finally, car l'objet ne sera pas nul (car il n'a pas été initialisé) et provoquera une exception.
La méthode Free
vérifie si l'objet est nul, l'initialisation des deux objets avec nil
évite les erreurs lors de leur libération s'ils n'ont pas été créés.