Exception safety

Exception safety is about taking care of the resources that you are using, such as allocated memory or opened files, both in the happy path through your code and in the case of an exception being thrown.

The problem lies in code such as

What happens to the memory which is allocated dynamically for the array if the function bar throws an exception? What surprises many developers is that the execution will skip all code lines after the call to bar in the local function and continue with the first line in the appropriate exception handler. The line where the dynamically array is deleted (using delete[]) is not going to be called at all! This means that the code in the example above is not exception safe, when an exception is thrown then the code will leak memory.

Even though all code lines after the call to bar will be skipped, all the local variables (i.e. allocated on the stack) declared in the function foo are going to be cleaned up. And this is a feature which C++ uses to deal with exception safety. The technique is called RAII (Resource Acquisition is Initialization) and stores variables and data structures on the local stack instead of on the free store directly. Now you object that it is impossible to always store all the data on the stack, you may not know how much data you are going to need when you write the program. The size of a variable is something which you probably want to determine at run time, depending on the input data to your program.

The C++ solution to this is to store a handle to the memory that you have allocated on the free store on the local stack. When that handle goes out of scope its destructor will be called and you simply make sure that you delete all the memory used in the destructor. This is the basic concept of the standard library containers, such as vector, list or map, or the smart pointers shared_ptr and unique_ptr.  To convert the example above into exception safe code, replace the call to the dynamic memory allocation into using std::vector like this.

The instance of the vector is allocated on the local stack, but internally it will call new[] to allocate the memory for the 25 values on the free store. When the vector goes out of scope, either because the function ends or an exception is thrown, then the destructor of the vector is going to be called and this will delete all the memory that was allocated on the free store.

The C++ standard library containers and data structures all use the RAII technique for making sure that no resources are being leaked. When you create a new class you should also use the RAII technique to make sure your code is exception safe. Other developers who are using or modifying your code expect that you have taken care of releasing the resources that you are using and don’t want to worry about cleaning up the mess after you. Make the C++ code that you write developer friendly and clean up your own mess!

Facebookgoogle_pluslinkedinmail

Move semantics

C++11 introduced the concept of move semantics, which is kind of an optimized way to copy data. When an object is moved, the contents of the object is taken over by the destination, this is different from copying the data because no valuable data is left in the old object. Move operations are therefore faster because no copying is involved, we simply move the contents of one object into another.

This changed very much how solid objects are handled in C++. Before, returning an object from a function was in many cases too expensive since all the data in the returned object would be copied to the new object. This led to the coding pattern of returning pointers to data, or to pass the return value as a parameter to a function.

However, using move semantics, we can instead return solid objects from functions without any performance penalties

The downside is that we now need to consider implementing the move constructor and move assignment operator when creating a class, in addition to the copy constructor, copy assignment operator and destructor.

Move constructor and Move assignment operator

These operators take the following form

In the move constructor and move assignment operator, you are free to steal whatever data there is in the other object. The double ample sand (&&) means an r-value reference, and this is a reference to an object which is about to die, meaning that it is going to go out of scope and we can take whatever is in it. So for example, if the class in the previous example contained a pointer to a buffer, we could take ownership of this in the move constructor, like this

However this contains a lot of duplicated code, which is very bad. A good way around this is to let the move constructor call the move assignment operator

Which is a lot shorter!

The standard containers are with C++11 also move-enabled, i.e. there are move constructor and move assignment operators defined in each of them. For example when returning a vector from a function, the created vector is moved to the outer scope and the internal pointer is moved from the dying object to the new object.

As a side note, there is sometimes a point in making a class movable by defining the move assignment operator and move constructor but prohibiting copying the class by deleting the copy constructor and copy assignment operator. An example of a class where this is done is the std::unique_ptr, which if it would allow copying would make the pointer not unique which is contrary to the whole point of the class!

Recommendations

  • To prevent memory leaks, always free any resource which may be present in the current object before taking over the other objects data in the move constructor and move assignment operators.
  • Always check for self-assignment in the move assignment operator.
  • Make use of the move assignment operator in the move constructor to remove redundancy.
  • If you define a move constructor, then also add a move assignment operator (see the C++ core guidelines).
Facebookgoogle_pluslinkedinmail

Why you should always use a virtual destructor

Virtual destructors are a must when you can delete an object through a pointer to a base class. Let me explain.

Say that you have a simple base class:

and a class deriving from the BaseClass with the addition of a resource which is supposed to be managed using RAII:

now what happens when you use this class:

since the base class doesn’t have a virtual destructor and ‘obj’ is pointing to a BaseClass, not to a DerivedClass, then the destructor of BaseClass is going to be called, but not the destructor of DerivedClass!! This means that the managed resource in DerivedClass is not going to be deleted properly when the object is deleted and thus we have a memory leak!

If instead the BaseClass would have a virtual destructor, like this:

then the constructors would be called in both the base class and the derived class and all contents will be correctly released.

Facebookgoogle_pluslinkedinmail

Shared pointer – std::shared_ptr

With C++11 came a new smart pointer class, std::shared_ptr.

Copyable

The shared pointer is allocated on the stack, exactly like the std::unique_ptr, but unlike the unique pointer is it possible to copy the shared pointer. Just like the unique_ptr will the contents which the smart pointer manages be deleted once the smart pointer goes out of scope. The difference is that the resource will only be deleted when all copies of the shared_ptr have gone out of scope. That is to say that as long as there is at least one handle to the shared memory then the resource will not be cleared.

Performance

The behavior of the std::shared_ptr is in practice implemented through reference counting, creating a new copy of a std::shared_ptr increases a counter of the number of live instances and as each copy goes out of scope this counter is decreased one step. When the counter finally reaches zero then the memory is released. This reference counting means that there is a slight overhead with using a shared_ptr compared to using the unique_ptr which doesn’t have this overhead.

std::weak_ptr

There is also one danger with the shared_ptr, it is possible to create dependency chains where two objects references each other through a shared_ptr and none of the two objects will ever be cleared because there is always one reference to each (by the other object). This “bug” can be resolve by using the third smart pointer introduced in C++11, the std::weak_ptr. A weak pointer is like a copy of a shared_ptr but creating it does not increase the reference count. Therefore, when the object is only reference by weak pointers then the memory will be deleted. The weak pointer can be converted into a std::shared_ptr (which you should do before trying to use it) and if the memory referenced to by the weak_ptr has already been released then you will get an empty shared_ptr back.

Creating – std::make_shared

You create instances of shared_ptr using the helper method std::make_shared. You can of course fill in the contents of the shared pointer yourself but the make_shared method is more efficient (one memory operation less than if you do it yourself) and has the advantage that if the constructor of the object throws an exception then the std::make_shared will make sure that no memory leak occurs.

 

Facebookgoogle_pluslinkedinmail

std::vector

The std::vector is one of the must useful containers of the standard library. It stores an array of elements on the free store (the heap) one after the other, just like you would get if you allocated the memory using new[]. The std::vector is very handy since it is very versatile and easy to use. Being a part of the standard library it will also manage its memory for you (using RAII) which avoids the memory leak problem. Since the objects are allocated contiguously in memory is this possible to use in combination with old code which expects an array of elements.

Creating

std::vector is always allocated on the stack. It can be allocated using uniform initialization:

or using just the size:

It is possible to add elements to the vector one at a time using push_back;

however, pushing back elements at the end of the vector is not recommended if the vector should hold hundreds of elements or more. When you push_back an element to the end then the underlying array will occasionally be resized by allocating a new array and copying all the elements from the old to the new array and this is a very time consuming process.

Iterating

You can iterate through each of the values in the vector using the new range-based for (C++11):

or using std::for_each and a lambda

Number of Elements

Unlike a dynamically allocated array (allocated using new[]), you don’t have to keep track of the size of the vector. Get the number of elements in the vector by calling the method size()

See also: Converting std::vector to C array and back

Facebookgoogle_pluslinkedinmail

Free store vs Heap

There is much confusion regarding the usage of the words stack, heap and free store. Most developers are using the stack and heap wrongly for C++.

Stack

The stack (actually the call stack) is the memory where all your local variables in a function will be located. The stack is a memory structure where all the function calls, from the start of the current thread, up to the currently executed function are stored together with the memory that they use. The variables which reside on the stack are stored there until the function where they reside returns. Once the method returns then all local (stack) variables will be cleaned up.

Heap

The heap is a legacy from C which should not be used in C++. Objects on the heap are allocated using malloc or calloc and released again using free. You should never use malloc or calloc to allocate an object in C++. This since these calls does not call the constructor of the object, leaving you with allocated memory for an invalid object.

Free Store

The free store is in C++ what the heap was in C. Objects on the free store are allocated using new or new[] and released again using delete or delete[]. Objects allocated using new or new[] are allocated and their constructor is being called once the memory is allocated. Objects destroyed using delete or delete[] have their destructor called before the memory is released again.

Facebookgoogle_pluslinkedinmail

Constructor – creating the object

The constructor is a special function used to setup an object to a valid state.

  • The constructor must have the same name as the class.
  • The constructor does not have a return type.
  • There can be many constructors for the same class, the difference between them is the number and type of the parameters.

A constructor without any parameters is called the default constructor. If you don’t write a default constructor then one will be created for you automatically and setup the object with default values (which may not be what you want).

The constructor of the object is together with the destructor an important part of the RAII paradigm.

Multiple constructors

A class can have many constructors, and one common problem is that these will usually perform the same initialization of the member variables thereby creating redundant code. With the interest of keeping your code DRY, you should consider to extract the common elements into separate functions. The, in many cases, most natural solution to this would be to make the constructors call each other – but there is a pitfall here. Calling one constructor from another will only work in C++11, so if you have a compiler which supports C++11 you can do the following (called delegating constructors):

If you don’t have a C++11 compiler then the common solution is to extract a separate function which does the initialization:

 

Private Constructor

Normally is the constructor of a class a public member function. If a class has a private constructor, then it is not possible to create instances of the class anywhere else but in the class itself. This can be handy if you want all instances to be created in exactly the same way or in the same location using a static factory method.

 

 

Facebookgoogle_pluslinkedinmail

RAII – Resource Acquisition Is Initialization

Resource Acquisition is Initialization (or RAII for short, usually pronounced by simply spelling out the letters R-A-I-I) is a programming technique where we make sure that resources are cleaned up when they are no longer needed by tying a resource to an object. The resource is kept as long as the object is alive and automatically released when the object is destroyed.

The resource that is being managed can be a segment of memory, a file handle, a network socket, a database handle or anything else which there is just a limited number of in the system and which we need to make sure we close properly after we are done with it.

The way RAII works is that we tie the resource to a class. When an instance of the class is created then the constructor of the object’s class is called to create the resource (or passed the resource to be managed). When the object is later destroyed (by going out of scope) then the destructor will automatically be called and here we write the code to release the resource again.

The name is somewhat difficult and controversial, some have suggested instead calling it Scope-Bound Resource Management but this has so far not been too successful.

I think an example of what I mean is necessary here. In the example below is a segment of memory allocated (using new[]) in the constructor of the File class and the memory is released again (using delete[]) in the destructor. The neat thing here is that the destructor will automatically be called when the object goes out of scope, as is done when the function main() in the example exits.

Notice: this is only done automatically for you if the File object is allocated as a local object, this is one of the reasons why you should never use new or delete.

The benefits of RAII is that it creates:

  • exception safety: a stack object will be destroyed at the end of the enclosing scope,  also if an exception is thrown from the code after the object is created.
  •  good locality: the code for allocating the resource is in the same class as the code for releasing the resource again.
  • encapsulation: the managed resource is located inside the owning class and not accessible outside of it.

Because of its benefits is RAII used extensively throughout the standard library classes.

As an example, the following code is using old C functions to write data to a text file NOT using RAII.

In the example above we didn’t use RAII to hold on to the resource (which in this case is the file handle FILE* f). This makes the code not exception safe, if anyone would later add a function call after the file has been opened and this method throws an exception then the call to fclose will not be executed at all, leaving the file opened and locked.

A better example is to instead use the standard library to open and write to the file:

in this example does the instance of the standard library class std::ofstream which we create on the first line hold on to the file resource and when the object goes out of scope when the function ends then the file will be closed automatically for us. Notice how much shorter and cleaner this code becomes. We don’t have to worry about closing the file since this is done for us.

References

  1. Stroustrup: Why doesn’t C++ provide a “finally” construct?

 

Facebookgoogle_pluslinkedinmail

Destructor

The destructor in a class is a special member function which takes care of cleaning up the contents of the object when it goes out of scope.

  • There can only be one destructor function per class.
  • The name of the destructor is the name of the class itself preceded with a tilde (~). It takes no arguments and does not have a return type.
  • The destructor is automatically called when an object goes out of scope.

A destructor is needed if the class holds or uses any resources which must be released when the object is destroyed, such as file handles or pointers to allocated memory. In a simple class which does not hold any resources then a destructor is not necessary since C++ will automatically clean up the memory that the object used. You also don’t need to write a destructor if the class holds resources through smart pointers (like unique_ptr) or standard library containers like std::vector as these will automatically delete themselves when they go out of scope. Notice that if you need to write a constructor in a class and intend to later on inherit from the class that you are writing now then you must make the destructor virtual (see the post on virtual destructor).

Example of a class where a destructor is necessary:

Example of a class using string from the standard library which makes it possible to avoid writing a destructor:

The destructor is an important piece in the automatic cleaning up of resources necessary for RAII.

Facebookgoogle_pluslinkedinmail