Search icon
Subscription
0
Cart icon
Close icon
You have no products in your basket yet
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Learning Boost C++ Libraries

You're reading from  Learning Boost C++ Libraries

Product type Book
Published in Jul 2015
Publisher
ISBN-13 9781783551217
Pages 558 pages
Edition 1st Edition
Languages
Author (1):
Arindam Mukherjee Arindam Mukherjee
Profile icon Arindam Mukherjee

Table of Contents (19) Chapters

Learning Boost C++ Libraries
Credits
About the Author
About the Reviewers
www.PacktPub.com
Preface
1. Introducing Boost 2. The First Brush with Boost's Utilities 3. Memory Management and Exception Safety 4. Working with Strings 5. Effective Data Structures beyond STL 6. Bimap and Multi-index Containers 7. Higher Order and Compile-time Programming 8. Date and Time Libraries 9. Files, Directories, and IOStreams 10. Concurrency with Boost 11. Network Programming Using Boost Asio C++11 Language Features Emulation Index

RAII


C++ programs frequently deal with system resources like memory, file and socket handles, shared memory segments, mutexes, and so on. There are well-defined primitives, some from the C Standard Library and many more from the native systems programming interfaces, which are used to request and relinquish these resources. Failing to guarantee the release of acquired resources can cause grave problems to an application's performance and correctness.

The destructor of a C++ object on the stack is automatically invoked during stack unwinding. The unwinding happens when a scope is exited due to control reaching the end of the scope, or by executing return, goto, break, or continue. A scope is also exited as a result of an exception being thrown. In either case, the destructor is guaranteed to be called. This guarantee is limited to C++ objects on the stack. It does not apply to C++ objects on the heap because they are not associated with a lexical scope. Furthermore, it does not apply to the aforementioned resources like memory and file descriptors, which are objects of Plain Old Data types (POD-types) and therefore do not have a destructor.

Consider the following C++ code using the new[] and delete[] operators:

char *buffer = new char[BUFSIZ];
… …
delete [] buffer;

The programmer was careful to release the buffer allocated. However, if another programmer came and flippantly wrote code to exit the scope somewhere between the calls to new and delete, then buffer would never be released and you would leak memory. Exceptions could arise in the intervening code too with the same result. This is true not just of memory but of any resource which requires a manual step to release, like delete[] in this case.

This is where we can utilize the guaranteed invocation of a destructor when exiting a scope to guarantee the clean-up of resources. We can create a wrapper class whose constructor acquires ownership of the resource and whose destructor releases the resource. A few lines of code can explain this technique that usually goes by the name Resource Acquisition is Initialization or RAII.

Listing A.1: RAII in action

 1 class String
 2 {
 3 public:
 4   String(const char *str = 0)
 5   {  buffer_ = dupstr(str, len_);  }
 6 
 7   ~String() { delete [] buffer_; }
 8
 9 private:
10   char *buffer_;
11   size_t len_;
12 };
13
14 // dupstr returns a copy of s, allocated dynamically.
15 //   Sets len to the length of s.
16 char *dupstr(const char *str, size_t& len) {
17   char *ret = nullptr;
18
19   if (!str) {
20     len = 0;
21     return ret;
22   }
23   len = strlen(str);
24   ret = new char[len + 1];
25   strncpy(ret, str, len + 1);
26
27   return ret;
28 }

The String class encapsulates a C-style string. We pass it a C-style string during construction, and it creates a copy of the passed string on the free store if it is not null. The helper function dupstr allocates memory for the String object on the free store using the the new[] operator (line 24). If allocation fails, operator new[] throws std::bad_alloc, and the String object never comes into being. In other words, resource acquisition must succeed for initialization to succeed. This is the other key aspect of RAII.

We use the String class in code as shown here:

 {
   String favBand("Led Zeppelin");
 ...   ...
 } // end of scope. favBand.~String() called.

We create an instance of String called favBand, which internally allocates a character buffer dynamically. When favBand goes out of scope normally or due to an exception, its destructor is called and it releases this buffer. You can apply this technique to all forms of resources that require manual release, and it will never let a resource leak creep in. The String class is said to own the buffer resource, that is, it has unique ownership semantics.

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime}