Resource Acquisition Is Initialization
Encyclopedia
Resource Acquisition Is Initialization (RAII, sometimes RIIA) is a programming idiom
Programming idiom
A programming idiom is a means of expressing a recurring construct in one or more programming languages. Generally speaking, a programming idiom is an expression of a simple task or algorithm that is not a built-in feature in the programming language being used, or, conversely, the use of an...
used in several object-oriented languages
Object-oriented programming language
This is a list of object-oriented programming programming languages.-Languages with object-oriented features:*ABAP*Ada 95*AmigaE*BETA*Blue*Boo*C++*C#*COBOL*Cobra*ColdFusion*Common Lisp*COOL*CorbaScript*Clarion*CLU*Curl*D*Dylan*E*Eiffel...
like C++
C++
C++ is a statically typed, free-form, multi-paradigm, compiled, general-purpose programming language. It is regarded as an intermediate-level language, as it comprises a combination of both high-level and low-level language features. It was developed by Bjarne Stroustrup starting in 1979 at Bell...
, D
D (programming language)
The D programming language is an object-oriented, imperative, multi-paradigm, system programming language created by Walter Bright of Digital Mars. It originated as a re-engineering of C++, but even though it is mainly influenced by that language, it is not a variant of C++...
and Ada
Ada (programming language)
Ada is a structured, statically typed, imperative, wide-spectrum, and object-oriented high-level computer programming language, extended from Pascal and other languages...
. The technique was invented by Bjarne Stroustrup
Bjarne Stroustrup
Bjarne Stroustrup ; born December 30, 1950 in Århus, Denmark) is a Danish computer scientist, most notable for the creation and the development of the widely used C++ programming language...
to deal with resource deallocation
Resource allocation (computer)
In computing, resource allocation is necessary for any application to be run on the system. When the user opens any program this will be counted as a process, and therefore requires the computer to allocate certain resources for it to be able to run...
in C++. In this language, the only code that can be guaranteed to be executed after an exception
Exception handling
Exception handling is a programming language construct or computer hardware mechanism designed to handle the occurrence of exceptions, special conditions that change the normal flow of program execution....
is thrown are the destructors
Destructor (computer science)
In object-oriented programming, a destructor is a method which is automatically invoked when the object is destroyed...
of objects residing on the stack
Stack (data structure)
In computer science, a stack is a last in, first out abstract data type and linear data structure. A stack can have any abstract data type as an element, but is characterized by only three fundamental operations: push, pop and stack top. The push operation adds a new item to the top of the stack,...
. Resources therefore need to be tied to the lifespan of suitable objects in order to gain automatic reclamation. They are acquired during initialization, when there is no chance of them being used before they are available, and released with the destruction of the same objects, which is guaranteed to take place even in case of errors.
RAII is vital in writing exception-safe C++ code: to release resources before permitting exceptions to propagate (in order to avoid resource leaks) one can write appropriate destructors once rather than dispersing and duplicating cleanup logic between exception handling blocks that may or may not be executed.
Language support
C++C++
C++ is a statically typed, free-form, multi-paradigm, compiled, general-purpose programming language. It is regarded as an intermediate-level language, as it comprises a combination of both high-level and low-level language features. It was developed by Bjarne Stroustrup starting in 1979 at Bell...
and D allow objects to be allocated on the stack
Call stack
In computer science, a call stack is a stack data structure that stores information about the active subroutines of a computer program. This kind of stack is also known as an execution stack, control stack, run-time stack, or machine stack, and is often shortened to just "the stack"...
and their scoping
Scope (programming)
In computer programming, scope is an enclosing context where values and expressions are associated. Various programming languages have various types of scopes. The type of scope determines what kind of entities it can contain and how it affects them—or semantics...
rules ensure that destructors are called when a local object's scope ends. By putting the resource release logic in the destructor, C++'s and D's scoping provide direct support for RAII.
The C
C (programming language)
C is a general-purpose computer programming language developed between 1969 and 1973 by Dennis Ritchie at the Bell Telephone Laboratories for use with the Unix operating system....
language does not directly support RAII, though there are some ad-hoc mechanisms available to emulate it. However, some compilers provide non-standard extensions that implement RAII. For example, the "cleanup" variable attribute extension of GCC
GNU Compiler Collection
The GNU Compiler Collection is a compiler system produced by the GNU Project supporting various programming languages. GCC is a key component of the GNU toolchain...
is one of them.
Typical uses
The RAII technique is often used for controlling mutex locks in multi-threaded applications. In that use, the object releases the lock when destroyed. Without RAII in this scenario the potential for deadlockDeadlock
A deadlock is a situation where in two or more competing actions are each waiting for the other to finish, and thus neither ever does. It is often seen in a paradox like the "chicken or the egg"...
would be high and the logic to lock the mutex would be far from the logic to unlock it. With RAII, the code that locks the mutex essentially includes the logic that the lock will be released when the RAII object goes out of scope. Another typical example is interacting with files: We could have an object that represents a file that is open for writing, wherein the file is opened in the constructor and closed when the object goes out of scope. In both cases, RAII only ensures that the resource in question is released appropriately; care must still be taken to maintain exception safety. If the code modifying the data structure or file is not exception-safe, the mutex could be unlocked or the file closed with the data structure or file corrupted.
The ownership of dynamically allocated memory (such as memory allocated with new in C++ code) can be controlled with RAII, such that the memory is released when the RAII object is destroyed. For this purpose, the C++ Standard Library defines the smart pointer
Smart pointer
In computer science, a smart pointer is an abstract data type that simulates a pointer while providing additional features, such as automatic garbage collection or bounds checking. These additional features are intended to reduce bugs caused by the misuse of pointers while retaining efficiency...
class
std::auto ptrAuto ptrauto_ptr is a class template available in the C++ Standard Library that provides some basic RAII features for C++ raw pointers....
that is deprecated in C++11 in favor of std::unique ptr
Smart pointer
In computer science, a smart pointer is an abstract data type that simulates a pointer while providing additional features, such as automatic garbage collection or bounds checking. These additional features are intended to reduce bugs caused by the misuse of pointers while retaining efficiency...
. Furthermore, smart pointer with shared-ownership semantics such as
tr1::shared_ptr
(defined in C++ by TR1 and marked for inclusion in the current C++11 standard), or policy based smart pointers such as Loki::SmartPtr
(from LokiLoki (C++)
Loki is the name of a C++ software library written by Andrei Alexandrescu as part of his book Modern C++ Design.The library makes extensive use of C++ template metaprogramming and implements several commonly used tools: typelist, functor, singleton, smart pointer, object factory, visitor and...
), can also be used to manage the lifetime of shared objects.
C++ example
The following RAII class is a lightweight wrapper of the C standard libraryC standard library
The C Standard Library is the standard library for the programming language C, as specified in the ANSI C standard.. It was developed at the same time as the C POSIX library, which is basically a superset of it...
file system calls.
The class
file
can then be used as follows:This works because the class
file
encapsulates the management of the FILE*
file handle. When file
objects are local to a function, C++ guarantees that they are destroyed at the end of the enclosing scope (the function in the example), and the file
destructor releases the file by calling std::fclose(file_)
. Furthermore, file
instances guarantee that a file is available by throwing an exception if the file could not be opened when creating the object.Local variables easily manage multiple resources within a single function: They are destroyed in the reverse order of their construction, and an object is only destroyed if fully constructed. That is, if no exception propagates from its constructor.
Using RAII-enabled resources simplifies and reduces overall code size and helps ensure program correctness.
C example using GCC
GNU Compiler Collection
The GNU Compiler Collection is a compiler system produced by the GNU Project supporting various programming languages. GCC is a key component of the GNU toolchain...
extensions
The GNU Compiler Collection
GNU Compiler Collection
The GNU Compiler Collection is a compiler system produced by the GNU Project supporting various programming languages. GCC is a key component of the GNU toolchain...
implements a non-standard extension to the C
C (programming language)
C is a general-purpose computer programming language developed between 1969 and 1973 by Dennis Ritchie at the Bell Telephone Laboratories for use with the Unix operating system....
language that allows it to support RAII: the "cleanup" variable attribute. For example, the following macro defines a variable with a given type and attaches a function to it that will be called when the variable goes out of scope:
This macro can then be used as follows:
In this example, the compiler arranges for the fclose function to be called before example_usage returns.
Finalizers
In JavaJava (programming language)
Java is a programming language originally developed by James Gosling at Sun Microsystems and released in 1995 as a core component of Sun Microsystems' Java platform. The language derives much of its syntax from C and C++ but has a simpler object model and fewer low-level facilities...
, objects are not allocated on the stack and must be accessed through references; hence, one cannot have automatic variables of objects that "go out of scope". Instead, all objects are dynamically allocated. In principle, dynamic allocation does not make RAII unfeasible per se; it could still be feasible if there were a guarantee that a "destructor" ("finalize") method would be called as soon as an object were pointed to by no references (i.e., if the object lifetime management were performed according to reference counting
Reference counting
In computer science, reference counting is a technique of storing the number of references, pointers, or handles to a resource such as an object, block of memory, disk space or other resource...
).
However, Java objects have indefinite lifetimes which cannot be controlled by the programmer, because, according to the Java Virtual Machine
Java Virtual Machine
A Java virtual machine is a virtual machine capable of executing Java bytecode. It is the code execution component of the Java software platform. Sun Microsystems stated that there are over 4.5 billion JVM-enabled devices.-Overview:...
specification, it is unpredictable when the garbage collector
Garbage collection (computer science)
In computer science, garbage collection is a form of automatic memory management. The garbage collector, or just collector, attempts to reclaim garbage, or memory occupied by objects that are no longer in use by the program...
will act. Indeed, the garbage collector may never act at all to collect objects pointed to by no references. Hence the "finalize" method of an unreferenced object might never be called or be called long after the object became unreferenced. Resources must thus be closed manually by the programmer, using something like the dispose pattern.
In Java versions prior to Java 7, the preceding example would be written like this:
In Java 7 and later, using the new try-with-resources construct, this pattern can be declared a bit more concisely (but is still essentially equivalent to the above code, assuming no exceptions are thrown by the close method):
(The class used in the statement must implement
java.lang.AutoCloseable
.) In both cases, the burden of releasing resources falls on the programmer each time a resource is used: The programmer must either explicitly write finally
blocks, or must remember to construct the object in the "try-with-resources" construct in order to ensure that the resource is released.Note, however, that at least one of the benefits of RAII-style coding is still applicable to Java: Construction and initialization can be tightly coupled. For instance, in the above examples, note that it is impossible for code to refer to the variable
logfile
before it points to a valid object, since the variable logfile
is declared explicitly final
in the first example (and is implicitly final in the second due to the semantics of the try-with-resources construct) and that in both cases it is initialized on the same line as it is declared, with a new
expression that both creates and initializes the object it will reference.Closure blocks
RubyRuby (programming language)
Ruby is a dynamic, reflective, general-purpose object-oriented programming language that combines syntax inspired by Perl with Smalltalk-like features. Ruby originated in Japan during the mid-1990s and was first developed and designed by Yukihiro "Matz" Matsumoto...
and Smalltalk
Smalltalk
Smalltalk is an object-oriented, dynamically typed, reflective programming language. Smalltalk was created as the language to underpin the "new world" of computing exemplified by "human–computer symbiosis." It was designed and created in part for educational use, more so for constructionist...
do not support RAII, but have a pattern that makes use of methods that pass resources to closure blocks. Here is an example in Ruby:
The
open
method ensures that the file handle is closed without special precautions by the code writing to the file. This is similar to Common LispCommon Lisp
Common Lisp, commonly abbreviated CL, is a dialect of the Lisp programming language, published in ANSI standard document ANSI INCITS 226-1994 , . From the ANSI Common Lisp standard the Common Lisp HyperSpec has been derived for use with web browsers...
's
unwind-protect
-based macros:Python
Python (programming language)
Python is a general-purpose, high-level programming language whose design philosophy emphasizes code readability. Python claims to "[combine] remarkable power with very clear syntax", and its standard library is large and comprehensive...
's
with
statement and context manager system is also similar and provides deterministic resource management within a block, doing away with the requirement for explicit finally
-based cleanup and release.Before entering the block, the context manager (in this case, a
file
object) has its __enter__
method called. Before exiting the block (including when this is due to an exception being raised), the context manager's __exit__
method is called.In C#, the same goal is accomplished by wrapping any object that implements the
IDisposable
interface in a using
statement. When execution leaves the scope of the using
statement body, the Dispose
method on the wrapped object is executed giving it a deterministic way to clean up any resources.Visual Basic 2005
Visual Basic .NET
Visual Basic .NET , is an object-oriented computer programming language that can be viewed as an evolution of the classic Visual Basic , which is implemented on the .NET Framework...
also supports the
using
statement.Disadvantages of scope bound resource management alternatives
Where both finalizers and closure blocks work as a good alternative to RAII for "shallow" resources, it is important to note however that the compositional properties of RAII differ greatly from these scope bound forms of resource management. Where RAII allows for full encapsulation of resources behind an abstraction, with scope bound resource management this isn't the case. In an environment that purely depends on scope bound resource management, "being a resource" becomes a property that is transitive to composition. That is, using only scope bound resource management, any object that is composed using a resource that requires resource management effectively itself becomes a resource that requires resource management. RAII effectively breaks the transitivity of this property allowing for the existence of "deep" resources to be effectively abstracted away.Lets for example say we have an object of type A that by composition holds an object of type B that by composition holds an object of type C. Now lets see what happens when we create a new implementation of C that by composition holds a resource R. R will have some
close
or release
method that must be invoked prior to C going out of scope. We could make C into a RAII object for R that invokes release
on destruction.Basically now we have the situation where from the point of view of R and C (shallow resources) , scope bound resource management alternatives functionally are fully equivalent to RAII. From a point of view of A and B (deep resources) however, we see a difference in the transitivity of "being a resource" emerging. With C as a RAII object, the interface and implementation of A, B and any code using a scoped A or B will remain unchanged and unaware of the newly introduced existence of "deep" resources. Without RAII however, the fact that C holds R means that C will need its own
release
method for proxying the release
of R. B will now need its own release
method for proxying the release of C. A will need its own release
method for proxying the release of B, and the scope where either A or B is used will also require of the alternative resource management techniques, where with RAII C provides the abstraction barrier that hides the implementation detail of "implemented using a resource" from the view of A, B and any users of an A or B. This difference shows that RAII effectively breaks the compositional transitivity of the "being a resource" property.Reference counting
Perl and CPythonCPython
CPython is the default, most-widely used implementation of the Python programming language. It is written in C. In addition to CPython, there are two other production-quality Python implementations: Jython, written in Java, and IronPython, which is written for the Common Language Runtime. There...
manage object lifetime by reference counting, making it possible to use RAII in a limited form. Objects that are no longer referenced are immediately released, so a destructor can release the resource at that time. However, object lifetime isn't necessarily bound to any lexical scope. One can store a reference to an object in a global variable, for example, thus keeping the object (and resource) alive indeterminately long. This makes it possible to accidentally leak resources that should have been released at the end of some scope. Also, in the case of Python, the actual garbage collection strategy is an implementation detail, and running with an alternative interpreter (such as IronPython or Jython) could result in the RAII implementation not working.
Ad-hoc mechanisms
Languages with no direct support for defining constructors and destructors sometimes still have the ability to support ad-hoc RAII methods using programmer idioms. CC (programming language)
C is a general-purpose computer programming language developed between 1969 and 1973 by Dennis Ritchie at the Bell Telephone Laboratories for use with the Unix operating system....
, for example, lacks direct support for these features, yet programming languages with such support are often implemented in C
C (programming language)
C is a general-purpose computer programming language developed between 1969 and 1973 by Dennis Ritchie at the Bell Telephone Laboratories for use with the Unix operating system....
, and fragile support can be achieved in C
C (programming language)
C is a general-purpose computer programming language developed between 1969 and 1973 by Dennis Ritchie at the Bell Telephone Laboratories for use with the Unix operating system....
itself, although at the cost of additional cognitive overhead on the part of the programmer.
The lack of any standardized idiom for dynamic object allocation beyond malloc
Malloc
C dynamic memory allocation refers to performing dynamic memory allocation in the C via a group of functions in the C standard library, namely malloc, realloc, calloc and free....
and free can be addressed numerous ways, such as through a programming idiom of having TNew, TDelete, and Tmethod functions for any given type T. The ability of throw to do non-local jumps can be simulated under Unix with the setjmp/longjmp library functions, and the syntactic sugar
Syntactic sugar
Syntactic sugar is a computer science term that refers to syntax within a programming language that is designed to make things easier to read or to express....
needed to make the result readable can be injected using the C preprocessor
C preprocessor
The C preprocessor is the preprocessor for the C and C++ computer programming languages. The preprocessor handles directives for source file inclusion , macro definitions , and conditional inclusion ....
. A C
C (programming language)
C is a general-purpose computer programming language developed between 1969 and 1973 by Dennis Ritchie at the Bell Telephone Laboratories for use with the Unix operating system....
compiler
Compiler
A compiler is a computer program that transforms source code written in a programming language into another computer language...
supporting variadic macro
Variadic macro
A variadic macro is a feature of the C preprocessor whereby a macro may be declared to accept a varying number of arguments.Variable-argument macros were introduced in the ISO/IEC 9899:1999 revision of the C programming language standard in 1999...
s and in-expression variable declarations, like gcc, makes code like the following possible - although needing to go outside of C
C (programming language)
C is a general-purpose computer programming language developed between 1969 and 1973 by Dennis Ritchie at the Bell Telephone Laboratories for use with the Unix operating system....
proper (the macros are actually textual substitutions performed by the preprocessor) causing difficulty both in maintenance and especially in interpreting debugger results.
There are many different, often partial, solutions to the problem, such as handling object cleanup with goto
Goto
goto is a statement found in many computer programming languages. It is a combination of the English words go and to. It performs a one-way transfer of control to another line of code; in contrast a function call normally returns control...
, code that creates objects for the exceptions, or addresses multithreading issues. The real weakness of not having direct language support for RAII features is in situations where code from multiple sources is being combined, and all the ad-hoc methods being used fail to interact properly, or worse yet, directly conflict with each other.
Additionally, in languages where the common idiom doesn't include exceptions, there can be significant resistance from the entrenched community to write code like the example above, instead of the superficially more compact, but unscalable, code below which implements the same basic function and error checking but without RAII or exceptions.
In such code, only block structure retains the shadow of RAII, and error handling now dominates the main function, error output must now be interpreted by the user rather than providing convenient catch hooks. Further, if the same style were converted to library code, those functions would now be rife with uninternationalized text strings. All of these factors tend to inhibit the implementation of sufficient error handling by programmers; it is common to ignore return values from fputc, and fclose, in particular, despite the fact that the failure of fputc could be due to a filesystem being full, and proceeding blithely could result in catastrophic data loss (a problem once exhibited by the compress
Compress
Compress is a UNIX compression program based on the LZC compression method, which is an LZW implementation using variable size pointers as in LZ78.- Description of program :Files compressed by compress are typically given the extension .Z...
program, leading to undesired, 100% file compression).
The biggest problem with ad-hoc mechanisms, even for projects where mixing with other ad-hoc approaches can be obviated, is one of questionable code resilience. Ad-hocs are typically specific to individual projects, and usually haven't been subjected to the same rigorous testing and code review that RAII and exception mechanisms are when supported as a primary language feature. It's far more reasonable for a team to base the success of a important project on the exception handling of an internationally supported C++
C++
C++ is a statically typed, free-form, multi-paradigm, compiled, general-purpose programming language. It is regarded as an intermediate-level language, as it comprises a combination of both high-level and low-level language features. It was developed by Bjarne Stroustrup starting in 1979 at Bell...
compiler, than to rely on an ad-hoc C
C (programming language)
C is a general-purpose computer programming language developed between 1969 and 1973 by Dennis Ritchie at the Bell Telephone Laboratories for use with the Unix operating system....
mechanism such as the example provided above, and usually even preferable to mechanisms constructed in house by the same team.
External links
- Sample Chapter "Gotcha #67: Failure to Employ Resource Acquisition Is Initialization" by Stephen Dewhurst
- Interview "A Conversation with Bjarne Stroustrup" by Bill Venners
- Article "The Law of The Big Two" by Bjorn Karlsson and Matthew Wilson
- Article "Implementing the 'Resource Acquisition is Initialization' Idiom" by Danny Kalev
- Article "RAII, Dynamic Objects, and Factories in C++" by Roland Pibinger
- Article "Managing Dynamic Objects in C++" by Tom Cargill
- Blog Entry "RAII in C++" by Jonathan Dodds