Related
I am usually making use of modern C++'s features like smart pointers and rarely using raw pointers as handlers for dynamically allocated objects. Therefore, I don't have much experience with deallocation. I've wondered whether the following code example would be a valid choice of design to prevent exception induced memory leak:
void HttpListener::spawnRequestHandler(const http_request& request) {
std::thread handlerThread([request](){
IRequestHandler* handler = new HttpRequestHandler(request);
try {
handler->handleRequest();
}
catch (...){
delete handler;
std::rethrow_exception(std::current_exception());
}
});
handlerThread.detach();
}
Here is already a good answer.
However, it seems there are more issues with the code. Where is the request handler raw pointer supposed to be cleaned up ?
Maybe it gets owned by http_request (unlikely) or deletes itself inside handleRequest()(also unlikely), we cannot see this from the example (but both would be bad practice). It looks like a memory leak.
Also there is no need to explicitly use the interface IRequestHandler.
To sum up, the code (in the thread) might be simplified to:
HttpRequestHandler handler(request);
handler.handleRequest();
Additionally you do not need pointers to base class, you can use references just as well:
IRequestHandler& handlerInterface = handler;
What you suggest will work, however, I would recommend against it.
C++ is one of very few languages that has the concept of RAII, which is created to do exception safe code.
In short, of you have a call, it gets/creates the owning thing it's constructor and does the cleanup in it's destructor.
Some very good examples of this are str::unique_ptr and std::scoped_lock. However this is also very useful if you have multiple return statements.
In this case, I would adapt the code to:
void HttpListener::spawnRequestHandler(const http_request& request) {
std::thread handlerThread([request](){
auto handler = std::make_unique<HttpRequestHandler>(request);
handler->handleRequest();
handler.release();
});
handlerThread.detach();
}
As you can see, the code is smaller and easier to read. And you can stop the delete after all ended correctly via the release. Not sure if that's a big in your original code. Though, if intended, this makes it explicit, which is easier to debug afterwards.
If you need other actions that need to happen at destruction, scope guard can be very useful. Not sure about the link, though, the presentation by Andrei Alexandrescu this is based on, had all features you can imagine.
Note: if you don't need the release, you can as well create the instance on the stack.
I would suggest to also put the memory allocation into the try block and be more specific on which exceptions to catch, e.g.
IRequestHandler* handler = nullptr;
try {
handler = new HttpRequestHandler(request);
handler->handleRequest();
}
catch(const std::bad_alloc& e) {
log("Not enough heap memory."); //however you log or use cout
}
catch(const HttpRequestHandlerExeption1& e) {
delete handler;
HttpRequestHandlerstd::rethrow_exception(std::current_exception());
}
.
.
.
delete handler;
A good post about catching multiple exceptions you can find here
I am using STL containers in my code (being developed in C++ using Visual Studio 2010)
I have never used exception handling with STL containers before. Since STL containers throw bad_alloc exception, I plan to use like in sample code shown below. Let's assume function() gets called in low memory situation.
Now, I am not sure if it is full proof code OR do I need to do any additional cleanup activity.
class MyClass
{
std::vector<int>* integer_vector;
public:
MyClass()
{
std::string message;
message += "my message"; // bad_alloc could be thrown from here
integer_vector = new std::vector<int>; // bad_alloc could be thrown from here
}
};
void function()
{
try
{
MyClass* myclass_ptr;
myclass_ptr = new (std::nothrow) MyClass;
if (myclass_ptr==NULL)
{
// ANY CLEANUP NEEDED HERE ?
return;
}
std::map<int, char> myintcharmap; // bad_alloc could be thrown from here
}
catch(...)
{
// ANY CLEANUP NEEDED HERE ?
return;
}
}
Please can someone have a look and help.
You have two main potential leaks in the code you show. Both of which arguably stem from using raw pointers. You should prefer using std::unique_ptr (if you have C++11) or other similar "smart" pointers to indicate ownership, and for exception safety in general. Modern guidance is to avoid almost all usage of new or delete; when they cannot be avoided, they need to be paired. Note that your code has two calls to new but none to delete.
Inside function, the core problem is you could fully allocate data "owned" by myclass_ptr, cause an exception in later allocations, and then not be able to clean it up as myclass_ptr is no longer in scope.
Let's say you fixed that so it cleaned up the MyClass instance if an exception occurred after its creation. Your code would still leak because inside MyClass there's currently a similar problem with integer_vector. Although you could follow the rule of three and write a destructor to handle this case, it's probably easier to use a smart pointer here as well.
Exception handling is much bigger, much more opinionated topic. I'll leave it with the summary that it's typically bad to catch exceptions and squash them (usually that's only legit in an outer loop of a program that needs specific kinds of stability). It's also typically bad to catch exceptions in a scope so narrow that you don't know how to handle them. (For example, how would function decide whether to try again, give up, or use another approach? Its caller, or the caller further on up the chain, may have more information and be in a better place to handle this.)
In most cases you should not deal with bad_alloc exceptions. Your try/catch should be removed, as well as if (myclass_ptr==NULL).
Ask yourself : if the process memory is exhausted, what could I possibly do ? Best thing you can hope is to log something, clean up / free the system resources, and let the program terminates. This is the only right thing to do.
You can do this by setting the new_handler (with set_new_handler). It will be called by the new operator if memory allocation failed.
std::set_new_handler(my_handler); // do your cleanup in 'my_handler'
Recently I am following the tutorials on rastertek and find that they suggest use a Shutdown() method for cleaning up instead of the class own destructor.The reason they mention is that the destructor is not guaranteed to be executed when calling some unsafe function like ExitThread().
However, I doubt if that method would get executed when even the destructor cannot be called. Indeed you can always call Shutdown() before you call ExitThread() but why not the same for the destructor? If I can do something before calling ExitThread(), I can certainly call the destructor as well.
Isn't placing the clean up code in the destructor more or less safer than using another method to do the trick? I know that releasing some vital resources like closing a file may need this separate method to do the trick. But are there any reasons other than that since this does not seem to be the case in the tutorials?
For the record, I know there is a similar question out there. But that one got no answer.
Isn't placing the clean up code in the destructor more or less safer than using another method to do the trick?
The problem here is that while ExitThread (and other functions like it) is a perfect API for C, with C++ code, it breaks stack unwinding.
The correct solution for C++ is to make sure you do not call ExitThread (and such) in code using anything with destructors.
Problem:
void thread_function()
{
raii_resource r { acquire_resource() };
ExitThread();
// problem: r.~raii_resource() not called
}
The shutdown solution:
void thread_function()
{
raii_resource r { acquire_resource() };
r.shutdown(); // release resources here
ExitThread();
// r.~raii_resource() still not called
}
The shutdown solution is not obvious at all in client code. As #stefan said, kill it with fire.
Better solution (than the Shutdown thing):
void thread_function()
{
{ // artificial scope where RAII objects live
raii_resource r { acquire_resource() };
}
// this space does not support RAII life
ExitThread();
}
RAII works fine here, but the artificial scope is not very elegant. On top, it's as inelegant as the shutdown solution (it requires a non-obvious artifice in client code).
Better (cleaner) solution:
template<typename F>
void run_thread(F functor)
{
functor(); // all RAII resources inside functor; this is simple and
// obvious from client code
ExitThread();
}
The only advantage to moving initialization out of the constructor, and for removing cleanup out of the destructor is when you've got a base class framework where you want to reliably call virtual methods during these stages.
Since the vtable is changing during construction/destruction calls to virtual functions don't resolve to the most derived instance. By having explicit Initialize/Shutdown methods you can be sure the virtual functions dispatch correctly.
Please note, this isn't an answer that advocates this approach, just one that is trying to work out why they've suggested it!
destructors are guaranteed to be called when an object is destroyed however thread clean up can require a tad more than just object destruction. Generally speaking cleanup methods are added when you need to handle releasing of shared resources, dealing with ancient libraries, etc.
Specifically you're dealing with the Win32 API which qualifies as an ancient c-style library considering ExitThread has been around longer than I have ...
With such approach you'll need to call Shutdown in all cases where the object should be destroyed - each time when it leaves the scope. In the case of exceptions (if they are used) you'll cannot call it. Destructor will be called automatically in these cases.
"I can certainly call the destructor as well" - calling the destructor explicitly is highly not recommended because it will be called automatically in any case. This should be avoided except only in special cases. If you mean this code from the tutorial:
System->Shutdown();
delete System;
then I don't see the difference because delete System; will call the destructor anyway.
In any case I would prefer
{
// work with System
...
}
mentioned in #utnapistim answer. I do not see any minuses in such way of coding, and also it is common way to specify scope. Even not going deep in the details of legacy ::ExitThread you gain auto cleanup. It is possible to work with WinApi with C++ RAII technique, look for instance at my code: multithreading sample project. Initial commit was bare WinAPI, and next commit introduced resource wrappers. You can compare both variants - second is much clearer, imho.
Consider this simple class that demonstrates RAII in C++ (From the top of my head):
class X {
public:
X() {
fp = fopen("whatever", "r");
if (fp == NULL)
throw some_exception();
}
~X() {
if (fclose(fp) != 0){
// An error. Now what?
}
}
private:
FILE *fp;
X(X const&) = delete;
X(X&&) = delete;
X& operator=(X const&) = delete;
X& operator=(X&&) = delete;
}
I can't throw an exception in the destructor. I m having an error, but no way to report it. And this example is quite generic: I can do this not only with files, but also with e.g posix threads, graphical resources, ... I note how e.g. the wikipedia RAII page sweeps the whole issue under the rug: http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization
It seems to me that RAII is only usefull if the destruction is guaranteed to happen without error. The only resources known to me with this property is memory. Now it seems to me that e.g. Boehm pretty convincingly debunks the idea of manual memory management is a good idea in any common situation, so where is the advantage in the C++ way of using RAII, ever?
Yes, I know GC is a bit heretic in the C++ world ;-)
RAII, unlike GC, is deterministic. You will know exactly when a resource will be released, as opposed to "sometime in the future it's going to be released", depending on when the GC decides it needs to run again.
Now on to the actual problem you seem to have. This discussion came up in the Lounge<C++> chat room a while ago about what you should do if the destructor of a RAII object might fail.
The conclusion was that the best way would be provide a specific close(), destroy(), or similar member function that gets called by the destructor but can also be called before that, if you want to circumvent the "exception during stack unwinding" problem. It would then set a flag that would stop it from being called in the destructor. std::(i|o)fstream for example does exactly that - it closes the file in its destructor, but also provides a close() method.
This is a straw man argument, because you're not talking about garbage collection (memory deallocation), you're talking about general resource management.
If you misused a garbage collector to close files this way, then you'd have the identical situation: you also could not throw an exception. The same options would be open to you: ignoring the error, or, much better, logging it.
The exact same problem occurs in garbage collection.
However, it's worth noting that if there is no bug in your code nor in the library code which powers your code, deletion of a resource shall never fail. delete never fails unless you corrupted your heap. This is the same story for every resource. Failure to destroy a resource is an application-terminating crash, not a pleasant "handle me" exception.
Exceptions in destructors are never useful for one simple reason: Destructors destruct objects that the running code doesn't need anymore. Any error that happens during their deallocation can be safely handled in a context-agnostic way, like logging, displaying to the user, ignoring or calling std::terminate. The surrounding code doesn't care because it doesn't need the object anymore. Therefore, you don't need to propagate an exception through the stack and abort the current computation.
In your example, fp could be safely pushed into a global queue of non-closeable files and handled later. The calling code can continue without problems.
By this argument, destructors very rarely have to throw. In practice, they really do rarely throw, explaining the widespread use of RAII.
First: you can't really do anything useful with the error if your file object is GCed, and fails to close the FILE*. So the two are equivalent as far as that goes.
Second, the "correct" pattern is as follows:
class X{
FILE *fp;
public:
X(){
fp=fopen("whatever","r");
if(fp==NULL) throw some_exception();
}
~X(){
try {
close();
} catch (const FileError &) {
// perhaps log, or do nothing
}
}
void close() {
if (fp != 0) {
if(fclose(fp)!=0){
// may need to handle EAGAIN and EINTR, otherwise
throw FileError();
}
fp = 0;
}
}
};
Usage:
X x;
// do stuff involving x that might throw
x.close(); // also might throw, but if not then the file is successfully closed
If "do stuff" throws, then it pretty much doesn't matter whether the file handle is closed successfully or not. The operation has failed, so the file is normally useless anyway. Someone higher up the call chain might know what to do about that, depending how the file is used - perhaps it should be deleted, perhaps left alone in its partially-written state. Whatever they do, they must be aware that in addition to the error described by the exception they see, it's possible that the file buffer wasn't flushed.
RAII is used here for managing resources. The file gets closed no matter what. But RAII is not used for detecting whether an operation has succeeded - if you want to do that then you call x.close(). GC is also not used for detecting whether an operation has succeeded, so the two are equal on that count.
You get a similar situation whenever you use RAII in a context where you're defining some kind of transaction -- RAII can roll back an open transaction on an exception, but assuming all goes OK, the programmer must explicitly commit the transaction.
The answer to your question -- the advantage of RAII, and the reason you end up flushing or closing file objects in finally clauses in Java, is that sometimes you want the resource to be cleaned up (as far as it can be) immediately on exit from the scope, so that the next bit of code knows that it has already happened. Mark-sweep GC doesn't guarantee that.
I want to chip in a few more thoughts relating to "RAII" vs. GC. The aspects of using some sort of a close, destroy, finish, whatever function are already explained as is the aspect of deterministic resource release. There are, at least, two more important facilities which are enabled by using destructors and, thus, keeping track of resources in a programmer controlled fashion:
In the RAII world it is possible to have a stale pointer, i.e. a pointer which points to an already destroyed object. What sounds like a Bad Thing actually enables related objects to be located in close proximity in memory. Even if they don't fit onto the same cache-line they would, at least, fit into the memory page. To some extend closer proximity could be achieved by a compacting garbage collector, as well, but in the C++ world this comes naturally and is determined already at compile-time.
Although typically memory is just allocated and released using operators new and delete it is possible to allocate memory e.g. from a pool and arrange for an even compacter memory use of objects known to be related. This can also be used to place objects into dedicated memory areas, e.g. shared memory or other address ranges for special hardware.
Although these uses don't necessarily use RAII techniques directly, they are enabled by the more explicit control over memory. That said, there are also memory uses where garbage collection has a clear advantage e.g. when passing objects between multiple threads. In an ideal world both techniques would be available and C++ is taking some steps to support garbage collection (sometimes referred to as "litter collection" to emphasize that it is trying to give an infinite memory view of the system, i.e. collected objects aren't destroyed but their memory location is reused). The discussions so far don't follow the route taken by C++/CLI of using two different kinds of references and pointers.
Q. When has RAII an advantage over GC?
A. In all the cases where destruction errors are not interesting (i.e. you don't have an effective way to handle those anyway).
Note that even with garbage collection, you'd have to run the 'dispose' (close,release whatever) action manually, so you can just improve the RIIA pattern in the very same way:
class X{
FILE *fp;
X(){
fp=fopen("whatever","r");
if(fp==NULL) throw some_exception();
}
void close()
{
if (!fp)
return;
if(fclose(fp)!=0){
throw some_exception();
}
fp = 0;
}
~X(){
if (fp)
{
if(fclose(fp)!=0){
//An error. You're screwed, just throw or std::terminate
}
}
}
}
Destructors are assumed to be always success. Why not just make sure that fclose won't fail?
You can always do fflush or some other things manually and check error to make sure that fclose will succeed later.
I've noticed RAII has been getting lots of attention on Stackoverflow, but in my circles (mostly C++) RAII is so obvious its like asking what's a class or a destructor.
So I'm really curious if that's because I'm surrounded daily, by hard-core C++ programmers, and RAII just isn't that well known in general (including C++), or if all this questioning on Stackoverflow is due to the fact that I'm now in contact with programmers that didn't grow up with C++, and in other languages people just don't use/know about RAII?
There are plenty of reasons why RAII isn't better known. First, the name isn't particularly obvious. If I didn't already know what RAII was, I'd certainly never guess it from the name. (Resource acquisition is initialization? What does that have to do with the destructor or cleanup, which is what really characterizes RAII?)
Another is that it doesn't work as well in languages without deterministic cleanup.
In C++, we know exactly when the destructor is called, we know the order in which destructors are called, and we can define them to do anything we like.
In most modern languages, everything is garbage-collected, which makes RAII trickier to implement. There's no reason why it wouldn't be possible to add RAII-extensions to, say, C#, but it's not as obvious as it is in C++. But as others have mentioned, Perl and other languages support RAII despite being garbage collected.
That said, it is still possible to create your own RAII-styled wrapper in C# or other languages. I did it in C# a while ago.
I had to write something to ensure that a database connection was closed immediately after use, a task which any C++ programmer would see as an obvious candidate for RAII.
Of course we could wrap everything in using-statements whenever we used a db connection, but that's just messy and error-prone.
My solution was to write a helper function which took a delegate as argument, and then when called, opened a database connection, and inside a using-statement, passed it to the delegate function, pseudocode:
T RAIIWrapper<T>(Func<DbConnection, T> f){
using (var db = new DbConnection()){
return f(db);
}
}
Still not as nice or obvious as C++-RAII, but it achieved roughly the same thing. Whenever we need a DbConnection, we have to call this helper function which guarantees that it'll be closed afterwards.
I use C++ RAII all the time, but I've also developed in Visual Basic 6 for a long time, and RAII has always been a widely-used concept there (although I've never heard anyone call it that).
In fact, many VB6 programs rely on RAII quite heavily. One of the more curious uses that I've repeatedly seen is the following small class:
' WaitCursor.cls '
Private m_OldCursor As MousePointerConstants
Public Sub Class_Inititialize()
m_OldCursor = Screen.MousePointer
Screen.MousePointer = vbHourGlass
End Sub
Public Sub Class_Terminate()
Screen.MousePointer = m_OldCursor
End Sub
Usage:
Public Sub MyButton_Click()
Dim WC As New WaitCursor
' … Time-consuming operation. '
End Sub
Once the time-consuming operation terminates, the original cursor gets restored automatically.
RAII stands for Resource Acquisition Is Initialization. This is not language-agnostic at all. This mantra is here because C++ works the way it works. In C++ an object is not constructed until its constructor completes. A destructor will not be invoked if the object has not been successfully constructed.
Translated to practical language, a constructor should make sure it covers for the case it can't complete its job thoroughly. If, for example, an exception occurs during construction then the constructor must handle it gracefully, because the destructor will not be there to help. This is usually done by covering for the exceptions within the constructor or by forwarding this hassle to other objects. For example:
class OhMy {
public:
OhMy() { p_ = new int[42]; jump(); }
~OhMy() { delete[] p_; }
private:
int* p_;
void jump();
};
If the jump() call in the constructor throws we're in trouble, because p_ will leak. We can fix this like this:
class Few {
public:
Few() : v_(42) { jump(); }
~Few();
private:
std::vector<int> v_;
void jump();
};
If people are not aware of this then it's because of one of two things:
They don't know C++ well. In this case they should open TCPPPL again before they write their next class. Specifically, section 14.4.1 in the third edition of the book talks about this technique.
They don't know C++ at all. That's fine. This idiom is very C++y. Either learn C++ or forget all about this and carry on with your lives. Preferably learn C++. ;)
For people who are commenting in this thread about RAII (resource acquisition is initialisation), here's a motivational example.
class StdioFile {
FILE* file_;
std::string mode_;
static FILE* fcheck(FILE* stream) {
if (!stream)
throw std::runtime_error("Cannot open file");
return stream;
}
FILE* fdup() const {
int dupfd(dup(fileno(file_)));
if (dupfd == -1)
throw std::runtime_error("Cannot dup file descriptor");
return fdopen(dupfd, mode_.c_str());
}
public:
StdioFile(char const* name, char const* mode)
: file_(fcheck(fopen(name, mode))), mode_(mode)
{
}
StdioFile(StdioFile const& rhs)
: file_(fcheck(rhs.fdup())), mode_(rhs.mode_)
{
}
~StdioFile()
{
fclose(file_);
}
StdioFile& operator=(StdioFile const& rhs) {
FILE* dupstr = fcheck(rhs.fdup());
if (fclose(file_) == EOF) {
fclose(dupstr); // XXX ignore failed close
throw std::runtime_error("Cannot close stream");
}
file_ = dupstr;
return *this;
}
int
read(std::vector<char>& buffer)
{
int result(fread(&buffer[0], 1, buffer.size(), file_));
if (ferror(file_))
throw std::runtime_error(strerror(errno));
return result;
}
int
write(std::vector<char> const& buffer)
{
int result(fwrite(&buffer[0], 1, buffer.size(), file_));
if (ferror(file_))
throw std::runtime_error(strerror(errno));
return result;
}
};
int
main(int argc, char** argv)
{
StdioFile file(argv[1], "r");
std::vector<char> buffer(1024);
while (int hasRead = file.read(buffer)) {
// process hasRead bytes, then shift them off the buffer
}
}
Here, when a StdioFile instance is created, the resource (a file stream, in this case) is acquired; when it's destroyed, the resource is released. There is no try or finally block required; if the reading causes an exception, fclose is called automatically, because it's in the destructor.
The destructor is guaranteed to be called when the function leaves main, whether normally or by exception. In this case, the file stream is cleaned up. The world is safe once again. :-D
RAII.
It starts with a constructor and destructor but it is more than that.
It is all about safely controlling resources in the presence of exceptions.
What makes RAII superior to finally and such mechanisms is that it makes code safer to use because it moves responsibility for using an object correctly from the user of the object to the designer of the object.
Read this
Example to use StdioFile correctly using RAII.
void someFunc()
{
StdioFile file("Plop","r");
// use file
}
// File closed automatically even if this function exits via an exception.
To get the same functionality with finally.
void someFunc()
{
// Assuming Java Like syntax;
StdioFile file = new StdioFile("Plop","r");
try
{
// use file
}
finally
{
// close file.
file.close(); //
// Using the finaliser is not enough as we can not garantee when
// it will be called.
}
}
Because you have to explicitly add the try{} finally{} block this makes this method of coding more error prone (i.e. it is the user of the object that needs to think about exceptions). By using RAII exception safety has to be coded once when the object is implemented.
To the question is this C++ specific.
Short Answer: No.
Longer Answer:
It requires Constructors/Destructors/Exceptions and objects that have a defined lifetime.
Well technically it does not need exceptions. It just becomes much more useful when exceptions could potentially be used as it makes controlling the resource in the presence of exceptions very easy.
But it is useful in all situations where control can leave a function early and not execute all the code (e.g. early return from a function. This is why multiple return points in C is a bad code smell while multiple return points in C++ is not a code smell [because we can clean up using RAII]).
In C++ controlled lifetime is achieved by stack variables or smart pointers. But this is not the only time we can have a tightly controlled lifespan. For example Perl objects are not stack based but have a very controlled lifespan because of reference counting.
The problem with RAII is the acronym. It has no obvious correlation to the concept. What does this have to do with stack allocation? That is what it comes down to. C++ gives you the ability to allocate objects on the stack and guarantee that their destructors are called when the stack is unwound. In light of that, does RAII sound like a meaningful way of encapsulating that? No. I never heard of RAII until I came here a few weeks ago, and I even had to laugh hard when I read someone had posted that they would never hire a C++ programmer who'd didn't know what RAII was. Surely the concept is well known to most all competent professional C++ developers. It's just that the acronym is poorly conceived.
A modification of #Pierre's answer:
In Python:
with open("foo.txt", "w") as f:
f.write("abc")
f.close() is called automatically whether an exception were raised or not.
In general it can be done using contextlib.closing, from the documenation:
closing(thing): return a context
manager that closes thing upon
completion of the block. This is
basically equivalent to:
from contextlib import contextmanager
#contextmanager
def closing(thing):
try:
yield thing
finally:
thing.close()
And lets you write code like this:
from __future__ import with_statement # required for python version < 2.6
from contextlib import closing
import urllib
with closing(urllib.urlopen('http://www.python.org')) as page:
for line in page:
print line
without needing to explicitly close
page. Even if an error occurs,
page.close() will be called when the
with block is exited.
Common Lisp has RAII:
(with-open-file (stream "file.ext" :direction :input)
(do-something-with-stream stream))
See: http://www.psg.com/~dlamkins/sl/chapter09.html
First of all I'm very surprised it's not more well known! I totally thought RAII was, at least, obvious to C++ programmers.
However now I guess I can understand why people actually ask about it. I'm surrounded, and my self must be, C++ freaks...
So my secret.. I guess that would be, that I used to read Meyers, Sutter [EDIT:] and Andrei all the time years ago until I just grokked it.
The thing with RAII is that it requires deterministic finalization something that is guaranteed for stackbased objects in C++. Languages like C# and Java that relies on garbage collection doesn't have this guarantee so it has to be "bolted" on somehow. In C# this is done by implementing IDisposable and much of the same usage patterns then crops up basicly that's one of the motivators for the "using" statement, it ensures Disposal and is very well known and used.
So basicly the idiom is there, it just doesn't have a fancy name.
RAII is a way in C++ to make sure a cleanup procedure is executed after a block of code regardless of what happens in the code: the code executes till the end properly or raises an exception. An already cited example is automatically closing a file after its processing, see answer here.
In other languages you use other mechanism to achieve that.
In Java you have try { } finally {} constructs:
try {
BufferedReader file = new BufferedReader(new FileReader("infilename"));
// do something with file
}
finally {
file.close();
}
In Ruby you have the automatic block argument:
File.open("foo.txt") do | file |
# do something with file
end
In Lisp you have unwind-protect and the predefined with-XXX
(with-open-file (file "foo.txt")
;; do something with file
)
In Scheme you have dynamic-wind and the predefined with-XXXXX:
(with-input-from-file "foo.txt"
(lambda ()
;; do something
)
in Python you have try finally
try
file = open("foo.txt")
# do something with file
finally:
file.close()
The C++ solution as RAII is rather clumsy in that it forces you to create one class for all kinds of cleanup you have to do. This may forces you to write a lot of small silly classes.
Other examples of RAII are:
unlocking a mutex after acquisition
closing a database connection after opening
freeing memory after allocation
logging on entry and exit of a block of code
...
It's sort of tied to knowing when your destructor will be called though right? So it's not entirely language-agnostic, given that that's not a given in many GC'd languages.
I think a lot of other languages (ones that don't have delete, for example) don't give the programmer quite the same control over object lifetimes, and so there must be other means to provide for deterministic disposal of resources. In C#, for example, using using with IDisposable is common.
RAII is popular in C++ because it's one of the few (only?) languages that can allocate complex scope-local variables, but does not have a finally clause. C#, Java, Python, Ruby all have finally or an equivalent. C hasn't finally, but also can't execute code when a variable drops out of scope.
I have colleagues who are hard-core, "read the spec" C++ types. Many of them know RAII but I have never really heard it used outside of that scene.
CPython (the official Python written in C) supports RAII because of its use of reference counted objects with immediate scope based destruction (rather than when garbage is collected). Unfortunately, Jython (Python in Java) and PyPy do not support this very useful RAII idiom and it breaks a lot of legacy Python code. So for portable python you have to handle all the exceptions manually just like Java.
RAII is specific to C++. C++ has the requisite combination of stack-allocated objects, unmanaged object lifetimes, and exception handling.