Published on

Writing Memory Safe C++ Code

Authors
  • avatar
    Name
    Skim
    Twitter

This article by Jacob Beningo discusses the recent recommendation by the NSA to use memory-safe programming languages and how this has sparked discussions about the use of languages like Rust in the embedded systems space. It highlights that while memory-safe languages can reduce memory-related bugs, they are not a universal solution. Developers can still encounter memory issues even when using such languages. He addresses the challenges in adopting memory-safe languages in the embedded space, including the time and cost involved in training engineers, dealing with legacy code, and ensuring compatibility with existing vendor toolchains. He argues that for many teams, switching to a memory-safe language might be unnecessary.

A few C++ techniques that can help developers improve memory safety presented in the article are:

  1. Smart Pointers: The use of smart pointers in modern C++ is recommended to replace raw pointers, which can lead to memory leaks and other issues. Smart pointers manage memory allocation and deallocation more effectively.
  2. Avoid Using Dynamic Memory and the Heap: Embedded developers are advised to avoid dynamic memory and the heap whenever possible, as these can introduce memory-related bugs like leaks and fragmentation. Disabling features like the standard template library (STL) and exceptions can help achieve this.
  3. RAII (Resource Acquisition Is Initialization): When dynamic memory and the heap must be used, developers can apply the RAII technique. It involves associating an object's lifecycle with its resources, ensuring that resources are properly initialized and freed when the object goes out of scope.

The Rule of Zero, Rule of Three, and Rule of Five

These are some guidelines in C++ programming related to the management of resources, especially when it comes to custom classes that manage memory or other resources like files. They help to ensure proper resource management and prevent issues like memory leaks and resource leaks. More specifically:

The Rule of Zero:

The Rule of Zero suggests that you should avoid manually managing resources whenever possible. Instead, rely on C++'s automatic resource management features. It means that you should prefer using smart pointers like std::shared_ptr or std::unique_ptr to manage resources like memory. These smart pointers automatically release the resources they manage when they go out of scope, preventing memory leaks. Also, use standard library containers and types that handle resource management internally, like std::vector, std::string, etc.

The Rule of Three

The Rule of Three pertains to classes that need to explicitly manage resources because they have custom destructors, copy constructors, or copy assignment operators. If you need to define one of these special member functions for a class (destructor, copy constructor, or copy assignment operator), you often need to define all three to ensure proper resource management. The three special functions are:

  1. Destructor: To release resources held by an object when it goes out of scope.
  2. Copy Constructor: To create a deep copy of an object when you copy it.
  3. Copy Assignment Operator: To assign the contents of one object to another.

When you define any of these three functions, it's usually an indication that your class may be managing resources, and you should follow the Rule of Three by defining all of them correctly. In modern C++, this rule is often extended to the "Rule of Five."

The Rule of Five

The Rule of Five is an extension of the Rule of Three and accounts for move semantics introduced in C++11. It encompasses the following special member functions:

  1. Destructor
  2. Copy Constructor
  3. Copy Assignment Operator
  4. Move Constructor: Allows the efficient transfer of resources from one object to another.
  5. Move Assignment Operator: Allows efficient resource transfer during assignment.

When a class manages resources and you define any of these five special functions, you should usually define all five to ensure proper resource management and efficient resource transfer.