Elective Object Oriented Programming in C++

Object Oriented Programming in C++Unit 96 min read

Dynamic Memory Allocation & Pointers: new, delete, malloc, free, pointers, references, and memory leaks

Unit 9 of Object Oriented Programming in C++ covers dynamic memory allocation using pointers, the new/delete operators, memory leaks, dangling pointers, and their role in efficient resource management. Learn how to allocate memory at runtime, avoid common pitfalls, and compare C-style (malloc/free) and C++ (new/delete)


Core Concepts: Pointers and Dynamic Memory

1. What is a Pointer?

A pointer is a variable that stores the memory address of another variable. It allows indirect access to data and enables dynamic memory allocation.

[object Object][object Object]VariablePointerActual Value
Pointer stores memory address of a variable (left) and dereferences to access its value (right).
  • Syntax:
    int x = 10;      // Integer variable
    int* ptr = &x;   // Pointer storing address of x
    cout << *ptr;    // Output: 10 (dereferencing)
    

2. Dynamic Memory Allocation

Unlike static memory (allocated at compile-time), dynamic memory is allocated at runtime using:

  • C++ Operators: new (allocate), delete (deallocate)
  • C Functions: malloc() (allocate), free() (deallocate)

Why Use Dynamic Memory?

  • Flexible memory usage (e.g., loading game assets of unknown size).
  • Avoids stack overflow for large data (e.g., processing NEPSE stock records).

Visual: Memory Allocation in C++

Key Observations:

  • new returns a pointer to the allocated memory.
  • delete frees memory but does not set the pointer to nullptr (risk of dangling pointer).

3. new vs. malloc and delete vs. free

Feature new/delete (C++) malloc/free (C)
Memory Type Handles objects (calls constructors/destructors) Raw memory blocks
Syntax int* ptr = new int(5); int* ptr = (int*)malloc(sizeof(int));
Safety Type-safe (no casting) Requires explicit casting
Error Handling Throws std::bad_alloc Returns NULL on failure
0123int* ptr1 = new int[4];malloc(4 * sizeof(int))
`new` (C++) vs. `malloc` (C): Both allocate 4 `int` blocks, but `new` calls constructor.

Example: Allocating an Array Dynamically

int* arr = new int[5];  // Allocates space for 5 integers
delete[] arr;           // Deallocate array (use `delete[]`!)

4. Common Pitfalls and Solutions

a) Memory Leaks

  • Cause: Forgetting to delete allocated memory.
  • Example:
    void leak() {
        int* ptr = new int(10);  // Memory leaked if not deleted!
    }
    
  • Fix: Always pair new with delete.

b) Dangling Pointers

  • Cause: Using a pointer after delete.
  • Example:
    int* ptr = new int(20);
    delete ptr;
    cout << *ptr;  // Undefined behavior!
    
  • Fix: Set pointer to nullptr after deletion:
    delete ptr;
    ptr = nullptr;
    

c) Double Free

  • Cause: Calling delete twice on the same pointer.
  • Fix: Check for nullptr before deletion:
    if (ptr != nullptr) delete ptr;
    

In the Real World

  1. Pathao’s Ride Allocation

    • Uses dynamic memory to manage real-time ride requests. Each request is stored in a linked list node allocated via new, ensuring scalability during peak hours (e.g., Dashain traffic in Kathmandu).
  2. Ncell’s Customer Database

    • Dynamically allocates memory for new subscriber records (e.g., Customer* newCustomer = new Customer(name, phone)), avoiding static limits.
  3. Game Asset Loading (e.g., Unreal Engine)

    • Loads textures/models at runtime using new (e.g., Texture* tex = new Texture("path/to/image.png")), freeing them when the level unloads.

Worked Example: Bank Loan Calculator

class Loan {
private:
    double principal;
    double* interestRates;  // Dynamically allocated array
public:
    Loan(double p, int years) {
        principal = p;
        interestRates = new double[years];
        // Populate rates (e.g., from NMBL’s current rates)
    }
    ~Loan() { delete[] interestRates; }  // Critical to avoid leaks!
};

Trace:

Step Action Memory State
Loan loan(10000, 5); Allocates interestRates[5] Heap: [0.05, 0.055, ...]
loan.~Loan() delete[] interestRates Heap: [Free, Free, ...]

5. Pointers vs. References

Feature Pointers (int*) References (int&)
Initialization Can be reassigned Must be initialized once
Null Value Can be nullptr Cannot be null
Syntax int* ptr = &x; int& ref = x;
Use Case Dynamic memory, arrays Function parameters (safer)

Example: Passing by Reference (Safe)

void increment(int& num) { num++; }  // Modifies original
int x = 5;
increment(x);  // x is now 6

6. Smart Pointers (Bonus: STL Integration)

To avoid manual memory management, use smart pointers from <memory>:

  • std::unique_ptr: Exclusive ownership (auto-deletes).
  • std::shared_ptr: Shared ownership (reference counting).

Example:

#include <memory>
std::unique_ptr<int> ptr = std::make_unique<int>(42);
// No need to call delete!

Exam Tip

  1. Memory Management Questions:

    • Always show before/after memory states in diagrams (like the Pathao ride queue example).
    • Highlight leaks/dangling pointers in code traces.
  2. Common Exam Patterns:

    • Short Notes: Define new/delete, malloc/free, and their differences (2 marks).
    • Code Debugging: Given a snippet, identify leaks/dangling pointers (5 marks).
    • Application: Relate to real systems (e.g., "How would NEPSE use dynamic memory for stock data?").
  3. Avoid:

    • Forgetting delete[] for arrays.
    • Using malloc/free in C++ without casting (prefer new/delete).

Key Formula to Remember:

  • Memory Address Calculation: For an array int arr[3], arr points to &arr[0], arr + 1 points to &arr[1].

Visual Summary:

Based on the PU BE Computer (PU) syllabus for Object Oriented Programming in C++, unit 9.

Discussion

Loading…