Ok, the question of the century :)
Before you say or think anything, let me tell you that I've read couple of similar questions about this very topic, but I didn't find clear solution for my problem. My case is specific, and typical for system programmers I think.
I have this situation very often. I hate gotos, don't really know why, probably because everybody is yelling that it's bad. But until now I did not find better solution for my specific scenario, and the way I do it currently might be uglier than the use of goto.
Here is my case: I use C++ (Visual C++) for Windows application development, and quite often I use bunch of APIs in my routines. Suppose following situation:
int MyMemberFunction()
{
// Some code... //
if (!SomeApi())
{
// Cleanup code... //
return -1;
}
// Some code... //
if (!SomeOtherApi())
{
// Cleanup code... //
return -2;
}
// Some more code... //
if (!AnotherApi())
{
// Cleanup code... //
return -3;
}
// More code here... //
return 0; // Success
}
So after each Api I have to check if it succeeded, and abort my function if it did not. For this, I use whole bunch of // Cleanup code... //, often pretty much duplicated, followed by the return statement. The function performs, say, 10 tasks (e.g. uses 10 Apis), and if task #6 fails, I have to clean up the resources created by previous tasks. Note that the cleanup should be done by the function itself, so exception handling cannot be used. Also, I can't see how much-talked RAII can help me in this situation.
The only way I've thought of, is to use goto to make jump from all such failure cases to one cleanup label, placed at the end of the function.
Is there any better way of doing this? Will using goto considered bad practice in such situation? What to do then? Such situation is very typical for me (and for system programmers like me, I believe).
P.S.: Resources that need to be cleanup up, are of different types. There might be memory allocations, various system object handles that need closure, etc.
UPDATE:
I think people still did not get what I wanted (probably I'm explaining badly). I thought the pseudo-code should be enough, but here is the practical example:
I open two files with CreateFile. If this step fails: I have to cleanup the already-open files handle(s), if any. I will later read part of one file and write into another.
I use SetFilePointer to position read pointer in first file. If this step fails: I have to close handles opened by previous step.
I use GetFileSize to get target file size. If api fails, or file size is abnormal, I have to make cleanup: same as in previous step.
I allocate buffer of specified size to read from first file. If memory allocation fails, I have to close file handles again.
I have to use ReadFile to read from first file. If this fails, I have to: release buffer memory, and close file handles.
I use SetFilePointer to position write pointer in second file. If this fails, same cleanup has to be done.
I have to use WriteFile to write to second file. If this fails, bla-bla-bla...
Additionally, suppose I guard this function with critical section, and after I call EnterCriticalSection in the beginning of the function, I have to call LeaveCriticalSection before every return statement.
Now note that this is very simplified example. There might be more resources, and more cleanup to be done - mostly same, but sometimes a little bit different, based on which step did fail. But let's talk within this example: how can I use RAII here?
Use of goto is not needed, it is error prone, resulting in redundant and rather unsafe code.
Use RAII and you do not have to use goto. RAII through smart pointers is ideal for your scenario.
You ensure all your resources in the scope are RAII managed(either use smart pointers or your own resource managing classes for them), whenever a error condition occurs all you have to do is return and RAII will magically free your resources implicitly.
RAII will work for this as long as the resources created by previous tasks are maintained in the form of classes/objects that clean up after themselves. You mentioned memory and system object handles, so let's use those as a starting point.
// non RAII code:
int MyMemberFunction() {
FILE *a = fopen("Something", "r");
if (!task1()) {
fclose(a);
return -1;
}
char *x = new char[128];
if (!task2()) {
delete [] x;
fclose(a);
return -2;
}
}
RAII-based code:
int MyMemberFunction() {
std::ifstream a("Something");
if (!task1())
return -1; // a closed automatically when it goes out of scope
std::vector<char> x(128);
if (!task2())
return -2; // a closed, x released when they go out of scope
return 0; // again, a closed, x released when they go out of scope
}
Also note that if you normally expect things to work, you can write the code to portray that a bit more closely:
int MyMemberFunction() {
bool one, two;
if ((one=task1()) && (two=task2()))
return 0;
// If there was an error, figure out/return the correct error code.
if (!one)
return -1;
return -2;
}
Edit: Although it's fairly unusual, if you really need to use c-style I/O, you can still wrap it up into a C++ class vaguely similar to an iostream:
class stream {
FILE *file;
public:
stream(char const &filename) : file(fopen(filename, "r")) {}
~stream() { fclose(file); }
};
That's obviously simplified (a lot), but the general idea works perfectly fine. There's a less obvious, but generally superior approach: an iostream actually uses a buffer class, using underflow for reading and overflow for writing (again, simplifying, though not as much this time). It's not terribly difficult to write a buffer class that uses a FILE * to handle the reading/writing. Most of the code involved is really little more than a fairly thin translation layer to provide the right names for the functions, rearrange the parameters to the right types and orders, and so on.
In the case of memory, you have two different approaches. One is like this, writing a vector-like class of your own that acts purely as a wrapper around whatever memory management you need to use (new/delete, malloc/free, etc.)
Another approach is to observe that std::vector has an Allocator parameter, so it's really already just a wrapper, and you can designate how it obtains/frees memory. If, for example, you really needed its back-end to be malloc and free, it would be fairly easy to write an Allocator class that used them. This way most of your code would follow normal C++ conventions, using std::vector just like anything else (and still supporting RAII as above). At the same time, you get complete control over the implementation of the memory management, so you can use new/delete, malloc/free, or something directly from the OS if needed (e.g., LocalAlloc/LocalFree on Windows).
Use boost:
scoped_ptr for handles, etc
scoped_lock to control mutex.
Related
It's more a philosophical type of question.
In C++ we have nice shiny idiom - RAII. But often I see it as incomplete. It does not well aligns with the fact that my application can be killed with SIGSEGV.
I know, I know, programms like that are malformed you say. But there is sad fact that on POSIX (specifically Linux) you can allocate beyond physical memory limits and meet SIGSEGV in the middle of the execution, working with correctly allocated memory.
You may say: "Application dies, why should you care about those poor destructors not being called?". Unfortunately there are some resources that are not automatically freed when application terminates, such as File System entities.
I am pretty sick right now of designing hacks, breaking good application design just to cope with this. So, what I am asking is for a nice, elegant solution to this kind of problems.
Edit:
It seems that I was wrong, and on Linux applications are killed by a kernel pager. In which case the question is still the same, but the cause of application death is different.
Code snippet:
struct UnlinkGuard
{
UnlinkGuard(const std::string path_to_file)
: _path_to_file(path_to_file)
{ }
~UnlinkGuard() {
unlink();
}
bool unlink() {
if (_path_to_file.empty())
return true;
if (::unlink(_path_to_file.c_str())) {
/// Probably some logging.
return false;
}
disengage();
return true;
}
void disengage() {
_path_to_file.clear();
}
private:
std::string _path_to_file;
};
void foo()
{
/// Pick path to temp file.
std::string path_to_temp_file = "...";
/// Create file.
/// ...
/// Set up unlink guard.
UnlinkGuard unlink_guard(path_to_temp_file);
/// Call some potentially unsafe library function that can cause process to be killed either:
/// * by a SIGSEGV
/// * by out of memory
/// ...
/// Work done, file content is appropriate.
/// Rename tmp file.
/// ...
/// Disengage unlink guard.
unlink_guard.disengage();
}
On success I use file. On failure I want this file to be missing.
This could be achived if POSIX had support for link()-ing of previously unlinked file by file descriptor, but there is no such feature :(.
So, what I am asking is for a nice, elegant solution to this kind of problems.
None exists, neither for C++ nor for other languages. You are faced with a fundamental physical reality here, not a design decision: what happens when the user pulls the plug? No programming solution can guard against that (well, there’s restore-upon-restart).
What you can do is catch POSIX signals and sometimes you can even handle them – but it’s flakey and there are tons of caveats, which another discussion on Stack Overflow details.
Most resources should not be cleared up after a segfault. If you want to do it anyway, simply collect those resources (or rather, handlers for their cleanup) in a global array, trap SIGSEGV, iterate through the cleanup routine array in the handler (hoping that the relevant memory is still intact), and perform the cleanup.
More specifically, for temporary files it helps to create them inside one of the system’s temporary folders. It’s understood that these don’t always get cleaned up by their respective applications, and either the system or the user will periodically perform cleanup instead.
Usually the solution, regardless of language or OS, is to clean up when you start the program, not (only) when you terminate. If your program can create temporary files that it cleans up on shutdown, clean up the temporary files when you start the program too.
Most everything else, like file handles, tcp connections, and so forth, is killed by the OS when your application dies.
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.
Lets say that I have a library which runs 24x7 on certain machines. Even if the code is rock solid, a hardware fault can sooner or later trigger an exception. I would like to have some sort of failsafe in position for events like this. One approach would be to write wrapper functions that encapsulate each api a:
returnCode=DEFAULT;
try
{
returnCode=libraryAPI1();
}
catch(...)
{
returnCode=BAD;
}
return returnCode;
The caller of the library then restarts the whole thread, reinitializes the module if the returnCode is bad.
Things CAN go horribly wrong. E.g.
if the try block(or libraryAPI1()) had:
func1();
char *x=malloc(1000);
func2();
if func2() throws an exception, x will never be freed. On a similar vein, file corruption is a possible outcome.
Could you please tell me what other things can possibly go wrong in this scenario?
This code:
func1();
char *x=malloc(1000);
func2();
Is not C++ code. This is what people refer to as C with classes. It is a style of program that looks like C++ but does not match up to how C++ is used in real life. The reason is; good exception safe C++ code practically never requires the use of pointer (directly) in code as pointers are always contained inside a class specifically designed to manage their lifespan in an exception safe manor (Usually smart pointers or containers).
The C++ equivalent of that code is:
func1();
std::vector<char> x(1000);
func2();
A hardware failure may not lead to a C++ exception. On some systems, hardware exceptions are a completely different mechanism than C++ exceptions. On others, C++ exceptions are built on top of the hardware exception mechanism. So this isn't really a general design question.
If you want to be able to recover, you need to be transactional--each state change needs to run to completion or be backed out completely. RAII is one part of that. As Chris Becke points out in another answer, there's more to state than resource acquisition.
There's a copy-modify-swap idiom that's used a lot for transactions, but that might be way too heavy if you're trying to adapt working code to handle this one-in-a-million case.
If you truly need robustness, then isolate the code into a process. If a hardware fault kills the process, you can have a watchdog restart it. The OS will reclaim the lost resources. Your code would only need to worry about being transactional with persistent state, like stuff saved to files.
Do you have control over libraryAPI implementation ?
If it can fit into OO model, you need to design it using RAII pattern, which guarantees the destructor (who will release acquired resources) to be invoked on exception.
usage of resource-manage-helper such as smart pointer do help too
try
{
someNormalFunction();
cSmartPtr<BYTE> pBuf = malloc(1000);
someExceptionThrowingFunction();
}
catch(...)
{
// Do logging and other necessary actions
// but no cleaning required for <pBuf>
}
The problem with exeptions is - even if you do re-engineer with RAiI - its still easy to make code that becomes desynchronized:
void SomeClass::SomeMethod()
{
this->stateA++;
SomeOtherMethod();
this->stateB++;
}
Now, the example might look artifical, but if you substitue stateA++ and stateB++ for operations that change the state of the class in some way, the expected outcome of this class is for the states to remain in sync. RAII might solve some of the problems associated with state when using exceptions, but all it does is provide a false sense of security - If SomeOtherMethod() throws an exception ALL the surrounding code needs to be analyzed to ensure that the post conditions (stateA.delta == stateB.delta) are met.
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.
I came across this article written by Andrei Alexandrescu and Petru Marginean many years ago, which presents and discusses a utility class called ScopeGuard for writing exception-safe code. I'd like to know if coding with these objects truly leads to better code or if it obfuscates error handling, in that perhaps the guard's callback would be better presented in a catch block? Does anyone have any experience using these in actual production code?
It definitely improves your code. Your tentatively formulated claim, that it's obscure and that code would merit from a catch block is simply not true in C++ because RAII is an established idiom. Resource handling in C++ is done by resource acquisition and garbage collection is done by implicit destructor calls.
On the other hand, explicit catch blocks would bloat the code and introduce subtle errors because the code flow gets much more complex and resource handling has to be done explicitly.
RAII (including ScopeGuards) isn't an obscure technique in C++ but firmly established best-practice.
Yes.
If there is one single piece of C++ code that I could recommend every C++ programmer spend 10 minutes learning, it is ScopeGuard (now part of the freely available Loki library).
I decided to try using a (slightly modified) version of ScopeGuard for a smallish Win32 GUI program I was working on. Win32 as you may know has many different types of resources that need to be closed in different ways (e.g. kernel handles are usually closed with CloseHandle(), GDI BeginPaint() needs to be paired with EndPaint(), etc.) I used ScopeGuard with all these resources, and also for allocating working buffers with new (e.g. for character set conversions to/from Unicode).
What amazed me was how much shorter the program was. Basically, it's a win-win: your code gets shorter and more robust at the same time. Future code changes can't leak anything. They just can't. How cool is that?
I often use it for guarding memory usage, things that need to be freed that were returned from the OS. For example:
DATA_BLOB blobIn, blobOut;
blobIn.pbData=const_cast<BYTE*>(data);
blobIn.cbData=length;
CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN, &blobOut);
Guard guardBlob=guardFn(::LocalFree, blobOut.pbData);
// do stuff with blobOut.pbData
I think above answers lack one important note. As others have pointed out, you can use ScopeGuard in order to free allocated resources independent of failure (exception). But that might not be the only thing you might want to use scope guard for. In fact, the examples in linked article use ScopeGuard for a different purpose: transcations. In short, it might be useful if you have multiple objects (even if those objects properly use RAII) that you need to keep in a state that's somehow correlated. If change of state of any of those objects results in an exception (which, I presume, usually means that its state didn't change) then all changes already applied need to be rolled back. This creates it's own set of problems (what if a rollback fails as well?). You could try to roll out your own class that manages such correlated objects, but as the number of those increases it would get messy and you would probably fall back to using ScopeGuard internally anyway.
Yes.
It was so important in C++ that even a special syntax for it in D:
void somefunction() {
writeln("function enter");
// c++ has similar constructs but not in syntax level
scope(exit) writeln("function exit");
// do what ever you do, you never miss the function exit output
}
I haven't used this particular template but I've used something similar before. Yes, it does lead to clearer code when compared to equally robust code implemented in different ways.
I have to say, no, no it does not. The answers here help to demonstrate why it's a genuinely awful idea. Resource handling should be done through re-usable classes. The only thing they've achieved by using a scope guard is to violate DRY up the wazoo and duplicate their resource freeing code all over their codebase, instead of writing one class to handle the resource and then that's it, for the whole lot.
If scope guards have any actual uses, resource handling is not one of them. They're massively inferior to plain RAII in that case, since RAII is deduplicated and automatic and scope guards are manual code duplication or bust.
My experience shows that usage of scoped_guard is far inferior to any of the short reusable RAII classes that you can write by hand.
Before trying the scoped_guard, I had written RAII classes to
set GLcolor or GLwidth back to the original, once I've drawn a shape
make sure a file has fclosed once I had fopened it.
reset a mouse pointer to its initial state, after I've changed it to gears/hourgrlass during a execution of a slow function
reset the sorting state of a QListView's back to its previous state, once I've temporarily finished with altering its QListViewItems -- I did not want the list to reorder itself everytime I changed the text of a single item...
using simple RAII class
Here's how my code looked like with my hand-crafted RAII classes:
class scoped_width {
int m_old_width;
public:
scoped_width(int w) {
m_old_width = getGLwidth();
setGLwidth(w);
}
~scoped_width() {
setGLwidth(m_old_width);
}
};
void DrawTriangle(Tria *t)
{
// GLwidth=1 here
auto guard = scoped_width(2); // sets GLwidth=2
draw_line(t->a, t->b);
draw_line(t->b, t->c);
draw_line(t->c, t->a);
setGLwidth(5);
draw_point(t->a);
draw_point(t->b);
draw_point(t->c);
} // scoped_width sets GLwidth back to 1 here
Very simple implementation for scoped_width, and quite reusable.
Very simple and readable from the consumer side, also.
using scoped_guard (C++14)
Now, with the scoped_guard, I have to capture the existing value in the introducer ([]) in order to pass it to the guard's callback:
void DrawTriangle(Tria *t)
{
// GLwidth=1 here
auto guard = sg::make_scoped_guard([w=getGLwidth()](){ setGLwidth(w); }); // capture current GLwidth in order to set it back
setGLwidth(2); // sets GLwidth=2
draw_line(t->a, t->b);
draw_line(t->b, t->c);
draw_line(t->c, t->a);
setGLwidth(5);
draw_point(t->a);
draw_point(t->b);
draw_point(t->c);
} // scoped_guard sets GLwidth back to 1 here
The above doesn't even work on C++11.
Not to mention that trying to introduce the state to the lambda this way hurts my eyes.
using scoped_guard (C++11)
In C++11 you have to do this:
void DrawTriangle(Tria *t)
{
// GLwidth=1 here
int previous_width = getGLwidth(); // explicitly capture current width
auto guard = sg::make_scoped_guard([=](){ setGLwidth(previous_width); }); // pass it to lambda in order to set it back
setGLwidth(2); // sets GLwidth=2
draw_line(t->a, t->b);
draw_line(t->b, t->c);
draw_line(t->c, t->a);
setGLwidth(5);
draw_point(t->a);
draw_point(t->b);
draw_point(t->c);
} // scoped_guard sets GLwidth back to 1 here
As you can see,
the scoped_guard snoppet requires
3 lines to keep previous value (state) and set it to a new one, and
2 stack variables (previous_width and guard, again) to hold the previous state
the hand-crafted RAII class requires
1 readable line to set new state and keep the previous one, and
1 stack variable (guard) to hold the previous state.
Conclusion
I think that examples such as
void some_function() {
sg::scoped_guard([](){ cout << "this is printed last"; }
cout << "this is printed first";
}
are no proof of the usefullness of scoped_guard.
I hope that somebody can show me why I don't get the expected gain from scoped_guard.
I am convinced that RAII can be exploited better by writing short hand-crafted classes, than using the more generic but hard to use scoped_guard