Example
This section provides a series of examples to illustrate how the use of a scope guard can aid in error handling.
Let’s consider this simple example that opens a file and inserts it into a cache.
void f (const char* file_name)
{
FILE* f = fopen(file_name, "rb+");
 
mutex.acquire();
file_cache.append(f);
mutex.release();
}
The above code has no error handling and is not safe. It does not consider control flow or what happens after the file is opened. If an exception is thrown or the function exits early, nothing ensures that the file is closed or that the mutex is released. We can fix this by reorganizing the code or adding a few try/catch blocks to handle exceptions.
 
void f (const char* file_name)
{
FILE* f = fopen(file_name, "rb+");
 
// this try/catch ensures that 'f' is closed
try {
mutex.acquire();
 
// this try/catch ensures that 'mutex' is released
try {
file_cache.append(f);
}
catch(...) {
mutex.release();
throw;
}
 
mutex.release();
 
} catch(...) {
fclose (f);
throw;
}
}
That’s an improvement -- except the code is now less efficient and more complicated. And this is a simple application; the more complex the flow, or special cases we have to handle, the more complicated the code will become.
To make this code safe is trivial, and the additional overhead is small.
 
void f (const char* file_name)
{
FILE* f = fopen(file_name, "rb+");
 
// this guard ensures 'f' is closed on exit from scope.
RWScopeGuard file_guard = rwtMakeScopeGuard(fclose, f); //1
 
mutex.acquire();
 
// this guard ensures 'mutex' is released on exit from scope.
RWScopeGuard lock_guard = rwtMakeScopeGuard(mutex, &Mutex::release); //2
 
file_cache.append(f); //3
 
file_guard.dismiss(); //4
}
//1 Creates a guard that ensures the file f is closed on exit from scope.
//2 Creates another guard to ensure that mutex is released on exit from scope.
//3 Inserts the file into the cache. At this point, there is no need to explicitly close the file f because the guard will call the function to close it.
//4 Dismisses the file guard. Since the file has by this time been successfully inserted into the cache, we do not want the file to be closed when we leave this scope.
Now our code safely, cleanly and efficiently ensures that all resources are cleaned up.