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

Unique Pointer – std::unique_ptr

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

This is a great class to use when you need to allocate an object which must have a life time longer than the current local scope. In old C++, this would be done by creating the object on the free store using new. It would then be up to you as a programmer to decide when the object is no longer necessary and then call delete on the pointer. The new unique pointer frees you from remembering when to call delete. The key feature of the unique pointer is that is just that, unique. There can be one and only one pointer to the managed object and no copies can ever be made. If you need a pointer which can be shared between many classes then you should instead go for shared_ptr.

The unique pointer is stored on the local scope and when it goes out of scope then the contents of the pointer will be deleted.

Non copyable

The key feature with the unique pointer is that it is unique, this means that no copies of the unique_ptr can ever be made. This has as a side effect that an object which owns a unique_ptr as a member variable can itself not be copied. If you think about it, then this is actually the same behavior as in old C++ when you instead would create a pointer using new and store the pointer as a member variable in a class. That pointer caused problems when you tried to make copies of the owning object, because who should own (and then also delete) the pointer after the copy was made? The original object or the copy? In practice this made the object not copyable unless you explicitly wrote an copy constructor and copy assignment operator. The difference is that in the old way would the program still compile and run. Modern C++ stops you from doing this, it tries to stop you from shooting yourself in the foot!

 Movable

The unique pointer is on the other hand movable, this means that it is possible to create a unique_ptr inside a function and then return the created pointer. It also means that objects owning a unique pointer will themselves also be movable without you having to do anything.

Make

C++11 introduced the std::make_shared function which made it possible to create a shared_ptr safely and easily. However, the make_unique function wasn’t added until C++14 simply because of an oversight in the review. If your compiler supports C++14 then you can create the unique pointer like this

where the parameters to the constructor of the class are passed in the parenthesis

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

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

Scope

The scope of a variable determines who can see and use the variable and for how long the variable will be available until it is destroyed.

Local scope

Function parameters and variables declared inside a function (local variables) have local scope. That is to say that they can only be seen inside the function that declares them. The local variables are destroyed when the function exits and can no longer be accessed after the function exits.

Local scope prevents naming collisions. It is possible to have two variables with the same name, as long as they are in different scopes!

Be aware that it is possible to have nested scopes where two variables can exist with the same name but in different scopes, one inside another.

What happens in the example above is that within the nested block is a new variable ‘x’ created and this variable has its scope set to the local block which is smaller than the function main. Inside the nested scope is the outer variable ‘x’ not accessible it is hidden from view (this is called name hiding), only the variable ‘x’ declared in the inner scope can be seen and modified.  Notice that it is generally bad practice to declare a new variable with the same name is a smaller scope. The code quickly gets much more confusing when you have to remember which variable with the name ‘x’ you are seeing.

In the same way is it possible to declare a local variable with the same name as a function parameter.

This is also a bad practice and should always be avoided since it makes the code so much more difficult to read.

 

Facebookgoogle_pluslinkedinmail