Object-Oriented Programming

RAII

Michael L. Collard, Ph.D.

Department of Computer Science, The University of Akron

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 crashes
  • Invalid output
  • Security vulnerabilities

C++ Pointers

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

C++ Pointer Problems I

C++ Pointer Problems II

Problem with the Problem

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

Programming Idiom

  • A recurring construct to fix a commonly occurring 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 object 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 resource
  • Boolean - Check if 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 Example: std::ofstream

RAII Example: std::ofstream Expanded

RAII Example: 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

C++ Smart Pointers

  • std::auto_ptr Deprecated: C++11, Removed: C++17
  • std::unique_ptr C++11
  • std::shared_ptr 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

Calculating Complexity

Example: xmlReadFile()

Custom Deleter

Separation of Concerns

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

Alternative Solutions

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