Resource acquisition is initialization: Difference between revisions

Content deleted Content added
top: added needed citations
m clean up; MOS:OVERLINK
Line 94:
 
==Benefits==
The advantages of RAII as a resource management technique are that it provides encapsulation, [[exception safety]] (for stack resources), and locality (it allows acquisition and release logic to be written next to each other).
 
Encapsulation is provided because resource management logic is defined once in the class, not at each call site. Exception safety is provided for stack resources (resources that are released in the same scope as they are acquired) by tying the resource to the lifetime of a stack variable (a local variable declared in a given scope): if an [[Exception handling|exception]] is thrown, and proper exception handling is in place, the only code that will be executed when exiting the current [[Scope (computer science)|scope]] are the destructors of objects declared in that scope. Finally, locality of definition is provided by writing the constructor and destructor definitions next to each other in the class definition.
Line 104:
==Typical uses==
 
The RAII design is often used for controlling [[mutex]] locks in [[thread (computing)#Multithreading|multi-threaded]] applications. In that use, the object releases the lock when destroyed. Without RAII in this scenario the potential for [[deadlock]] 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 execution leaves the scope of the RAII object.
 
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 execution leaves the object's scope. In both cases, RAII ensures only 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.
 
Ownership of dynamically allocated objects (memory allocated with <code>new</code> in C++) can also be controlled with RAII, such that the object is released when the RAII (stack-based) object is destroyed. For this purpose, the [[C++11]] standard library defines the [[smart pointer]] classes <code>[[Smart pointer#unique_ptr|std::unique_ptr]]</code> for single-owned objects and <code>[[Smart_pointer#shared_ptr_and_weak_ptr|std::shared_ptr]]</code> for objects with shared ownership. Similar classes are also available through <code>[[auto ptr|std::auto_ptr]]</code> in C++98, and <code>boost::shared_ptr</code> in the [[Boost (C++ libraries)|Boost libraries]].
 
== Compiler "cleanup" extensions ==
Line 145:
| issue=2
| year=2008
| url=https://web.eecs.umich.edu/~weimerw/p/weimer-toplas2008.pdf}}</ref>{{rp|8:27}} This can be achieved by using [[smart pointer]]spointers to manage all heap objects, with weak-pointers for cyclically referenced objects.
 
In C++, stack unwinding is only guaranteed to occur if the exception is caught somewhere. This is because "If no matching handler is found in a program, the function terminate() is called; whether or not the stack is unwound before this call to terminate() is implementation-defined (15.5.1)." (C++03 standard, §15.3/9).<ref>{{cite web
Line 166:
| author=hobbs
| date=2011-02-08
| access-date=2019-03-09}}</ref> manage object lifetime by [[reference counting]], which makes it possible to use RAII. Objects that are no longer referenced are immediately destroyed or finalized and released, so a [[Destructor (computer programming)|destructor]] or [[finalizer]] can release the resource at that time. However, it is not always idiomatic in such languages, and is specifically discouraged in Python (in favor of [[context manager]]s and ''finalizers'' from the ''weakref'' package).
 
However, object lifetimes are not necessarily bound to any scope, and objects may be destroyed non-deterministically or not at all. This makes it possible to accidentally leak resources that should have been released at the end of some scope. Objects stored in a [[static variable]] (notably a [[global variable]]) may not be finalized when the program terminates, so their resources are not released; CPython makes no guarantee of finalizing such objects, for instance. Further, objects with circular references will not be collected by a simple reference counter, and will live indeterminately long; even if collected (by more sophisticated garbage collection), destruction time and destruction order will be non-deterministic. In CPython there is a cycle detector which detects cycles and finalizes the objects in the cycle, though prior to CPython 3.4, cycles are not collected if any object in the cycle has a finalizer.<ref>{{cite web