Object-Oriented Programming

RAII

Michael L. Collard, Ph.D.

Department of Computer Science, The University of Akron

Automatic Variables

  • Constructor called when the declaration is reached
  • Destructor is called right before the block exits
  • Order of destructor calls is inverse of constructor order

Software View of Resources

  • Memory
  • File handles (e.g., file descriptors)
  • Network connections
  • Locks & semaphores
  • Database connections

Resource must be…

  • Properly allocated
  • Properly initialized
  • Checked for validity before use
  • Properly deallocated

Resource Problems

  • Improper initialization
  • Use when invalid
  • Resource leak (never deallocated)
  • Double free (deallocation more than once)

Effect of Improperly-Used Resources

  • Exceed resource limits
  • Program crash
  • Invalid output
  • Security vulnerabilities

C++ Pointers

  • Pointers to memory
  • Limits on the amount of memory available to a program/process
  • Good pointer usage is not easy to do

C++ Pointer Problems

Avoiding C++ Pointer Problems

  • Behavioral issue
  • Requires complex tools to detect, with lots of false positives
  • Must have a scenario for each usage pattern
  • Good design can prevent the problem from occurring

Programming Idiom

A recurring construct to fix a commonly occurring coding problem

  • Not a direct feature of the programming language, but a combination of features to solve the problem
  • Typically, this is a design problem
  • Related to design patterns which we will discuss soon

RAII Idiom

Resource Acquisition Is Initialization

  • Holding a resource is tied to an object's lifetime
  • Constructor: Allocate resource
  • Destructor: Deallocate resource
  • Prevents resource leaks, double-free, use when invalid

RAII Interface

  • Constructor - Allocate resource
  • Destructor - Deallocate resource
  • Access - Direct access to a resource
  • Boolean - Check if the resource exists (i.e., has been allocated and is still valid)
  • Copy, Assignment - Transfer resource control to new RAII object
  • Deallocate - Deallocate resource before Destructor (safely)

RAII: std::ofstream

RAII: std::unique_lock

Smart Pointers

A wrapper type that makes pointers safer

  • How?
  • Automatic initialization with nullptr
  • Convertible to bool for validity checking
  • Automatic destructor call for deallocation of the contained resource

C++ Smart Pointers

  • std::auto_ptr
    • Deprecated in C++11, Removed in C++17
  • std::unique_ptr
    • Added C++11
  • std::shared_ptr
    • Added C++11

Pointer Use Cases

  • Use Case: Optional types
    • Solution: std::optional
  • Use Case: Lazy Initialization
    • Solution: About to find out
  • Use Case: Existing libraries that use pointers
    • Solution: About to find out

Use Case: Lazy Initialization

Delaying the construction of an object until (or if) it is needed

  • Primarily for resource expensive objects
  • Directly, e.g., sizeof(Data), store a large amount of data
  • Use a large number of resources
    • File handles
    • Network connections
    • Memory
    • Any resource

Lazy Initialization with Pointers

std::unique_ptr

Use Case: Existing library with pointers

Example: xmlReadFile()

  • Concerns
  • libxml2 functions, e.g., xmlReadFile
  • error handling for srcMLXPathCount()
  • deallocate with xmlFreeDoc(), etc. with error handling
  • Full Example

Custom Deleter

  • Concerns
  • libxml2 functions, e.g., xmlReadFile
  • error handling for srcMLXPathCount()
  • deallocate with xmlFreeDoc(), etc. with error handling
  • Full Example

Comparison

Specialization of default_delete<>

Alternative Solutions

  • Create custom C++ wrapper for every libxml2 function used
  • Use goto and other constructs in the code

Conclusion

  • RAII behavior prevents resource errors without any additional burden on the developer
  • Ensures proper behavior
  • Makes the resource much easier to work with, e.g., don't have to explicitly close()
  • All resources should be built with RAII behavior