Examples of Common C++ Memory Errors

In addition to the classic case covered previously, there are several more aspects of C++ programming that tend to cause memory errors. The following set of tables describes these situations. Note that the SimpleString used here is the corrected version, rather than the broken one used to illustrate dangling references. Article three in this series will discuss the corrected version of SimpleString in detail.

Errors in Function (or Method) Calls and Returns

Error: Returning a Reference (or Pointer) to a Local Object

The local object is destroyed when the function returns. In general, anything inside curly braces is a scope; if you define a local object (i.e. non- static) inside of a scope (as shown in the example), it no longer exists after the closing curly brace of that scope.

Result: dangling reference.

Example:

Returning a const Reference Parameter by const Reference

The C++ compiler is allowed to create an unnamed temporary object for any const reference parameter. After all, you promise not to change the parameter when you declare it const. Unfortunately, the unnamed temporary goes out of scope as soon as control leaves the function, so if you return a const reference parameter by const reference, a dangling reference can result.

Result: dangling reference.

Passing an Object by Value

When a function parameter is an object, rather than a pointer or a reference to one, then the argument (supplied during a call to the function) for that parameter is passed by value. The compiler will make a copy of the argument (the copy constructor will be invoked) in order to generate the function call. If the argument’s type is a derived class of the parameter, then the famous object slicing problem occurs. Any derived class functionality ? including overridden virtual methods ? is simply thrown away. The function gets what it asked for: its own object of the exact class that was specified in the declaration.

While all of this makes perfect sense to the compiler, it is often counterintuitive to the programmer. When you pass an object of the derived class, you expect the overridden virtual methods to be called. After all, this is what virtual methods are for. Unfortunately, it won’t work like that if a derived object is passed by value.

Result: derived parts are “sliced off.” Depending on your design, there may be no memory-related issues, but the slicing problem is important enough to be mentioned here.

Returning a Reference to a Dynamically Allocated Object

Your callers are highly unlikely to take an address of the reference and deallocate the object, especially if the return value is used inside of an expression instead of being immediately saved into a variable.

Result: memory leak.

By George Belotsky Initially published on Linux DevCenter (http://www.linuxdevcenter.com/)