Resource acquisition is initialization
En programmation orientée objet, resource acquisition is initialization, abrégé RAII et traduisible littéralement par l'acquisition d'une ressource est une initialisation, est une technique utilisée dans plusieurs langages orientés objet, comme C++, D et Ada. Cette technique, inventée par Bjarne Stroustrup[1], permet de s'assurer, lors de l'acquisition d'une ressource, que celle-ci sera bien libérée en liant cette acquisition à la durée de vie d'un objet : la ressource est acquise durant l'initialisation de l'objet, il est alors possible de l'utiliser tant que la ressource est disponible et elle est libérée au moment de la destruction de l'objet, cette destruction étant garantie même en cas d'erreur.
En C++, les objets résidant sur la pile sont automatiquement détruits lors de la sortie de la portée, y compris dans le cas d'une levée d'exception [2]; leur destructeur est appelé avant que l'exception ne se propage.
La technique RAII aide à l'écriture de code plus résistant aux exceptions : pour libérer une ressource avant de permettre à l'exception de se propager, on peut écrire un destructeur approprié plutôt que de disséminer et multiplier les instructions de nettoyage entre les blocs de prise en compte des exceptions.
Langages supportant la technique RAII
Les langages C++ et D permettent l'allocation d'objets sur la pile et leurs règles de portée garantissent que lorsque la portée d'un objet s'achève, son destructeur est automatiquement appelé. En plaçant les instructions de libération des ressources dans le destructeur, les règles de portée du C++ et du langage D permettent l'utilisation de la technique RAII.
Le langage Rust, de son côté, applique cette technique en s'assurant, dès la compilation, que toutes les ressources allouées dynamiquement sont liées à un objet de la pile[3]. Cette sévérité du compilateur permet d'éviter la majorité des fuites de mémoire en obligeant l'objet à libérer les ressources qu'il possède.
Cas d'utilisation
La technique RAII est souvent utilisée pour contrôler les mutex des applications multithreadées. Dans ce cas, l'objet relâche le mutex, s'il l'avait obtenu, au moment de sa destruction. Un autre exemple type est celui de la gestion de fichier, où la classe fichier ferme le fichier associé, si celui-ci a pu être ouvert, au moment de sa destruction.
La gestion de la mémoire allouée dynamiquement (par exemple par l'utilisation de new en C++) peut être contrôlée par RAII, de telle sorte que la mémoire soit libérée quand l'objet est détruit. Suivant cette logique, la bibliothèque standard C++ définit les classes de pointeurs intelligents std::shared_ptr
pour les objets à propriétaire partagé et std::unique_ptr
pour les objets à propriétaire unique. Des classes similaire telle que std::auto_ptr
et boost::shared_ptr
(définis parmi les bibliothèques C++ Boost) peuvent être utilisés pour gérer la durée de vie des objets en C++98.
Références
- (en) Bjarne Stroustrup, The Design and Evolution of C++, Reading, Addison-Wesley, , 4e Ă©d., 461 p. (ISBN 978-0-201-54330-8, LCCN 93050758)
- (en) Bjarne Stroustrup, Exception Safety : Concepts and Techniques, , PDF (lire en ligne)
- (en) « The Rust Pointer Guide »