Siksha Sarovar

Siksha Sarovar (sikshasarovar.com) is a free educational web application that helps students in India learn programming and prepare for academic and competitive exams. The platform offers structured coding courses (C, C++, Python, Java, HTML, CSS, PHP, Power BI, AI, Machine Learning, Data Science), complete university curriculum notes for BCA/MCA students with previous year question papers, Class 10 and Class 12 CBSE/HBSE school notes, and dedicated preparation material for SSC, UPSC, Banking, Railway and other government exams. Browsing the site is completely free and requires no account. Users may optionally sign in with Google solely to save their learning progress, quiz scores and personal preferences across devices.

Privacy Policy | Terms of Service | Contact Siksha Sarovar | About Siksha Sarovar

v4.0.9 · PWA
Siksha Sarovar logo
Siksha Sarovar
Your Learning Universe

Siksha Sarovar is a free e-learning platform for coding courses, BCA university notes and competitive exam preparation. Optional Google sign-in saves your learning progress across devices.

Initializing knowledge base…
Compiling modules 0%

1.4 Dynamic Memory — new, delete, and Allocation for Arrays

Lesson 6 of 22 in the free Object Oriented Programming with C++ notes on Siksha Sarovar, written by Rohit Jangra.

1.4 Dynamic Memory — new, delete, and Allocation for Arrays

Memory Model in C++

A C++ program's memory is divided into several regions:

   ┌──────────────────────┐  High address
   │      Stack           │  ← Local vars, function call frames
   │         ↓            │
   │                      │
   │         ↑            │
   │      Heap            │  ← new / malloc allocations
   ├──────────────────────┤
   │    BSS               │  ← Uninitialized globals/statics (zero)
   │    Data              │  ← Initialized globals/statics
   │    Text / Code       │  ← Program instructions (read-only)
   └──────────────────────┘  Low address
RegionStoresLifetimeManagement
StackLocal variables, function framesFunction scopeAutomatic
HeapDynamic allocationsUntil manually freedManual
DataInitialized globals/staticsProgram lifetimeAutomatic
BSSUninitialized globals/staticsProgram lifetimeAutomatic
TextExecutable codeProgram lifetimeRead-only

Why dynamic allocation?

  • Size unknown at compile time — need to ask user for array size
  • Lifetime must exceed scope — return an object from a function
  • Large objects — stack has limited size (~8 MB typically)
  • Polymorphism — base pointer to derived object
  • Data structures — linked lists, trees, graphs

---

new Operator

The new operator allocates memory on the heap and returns a pointer to it.

Allocate a single value

int* p = new int;         // allocate one int (uninitialised)
int* q = new int(42);     // allocate one int, initialise to 42
int* r = new int{42};     // C++11 brace-init form

*p = 10;
cout << *p;               // 10

Allocate an object

class Student {
public:
    int id;
    Student(int i) : id(i) {}
};

Student* s = new Student(101);
cout << s->id;             // 101

Allocate an array

int* arr = new int[5];           // array of 5 ints (uninitialised)
int* arr2 = new int[5]();        // array of 5 ints, zero-initialised
int* arr3 = new int[5]{1,2,3,4,5}; // brace-init (C++11+)

for (int i = 0; i < 5; i++) arr[i] = i + 1;
for (int i = 0; i < 5; i++) cout << arr[i] << " ";

---

delete Operator

Every new must be matched by a delete. Failing to delete = memory leak.

Delete single value

int* p = new int(42);
// ... use p
delete p;        // frees memory; p is now a dangling pointer
p = nullptr;     // optional but good practice

Delete array — note the brackets!

int* arr = new int[5];
// ... use arr
delete[] arr;    // bracket form for arrays
Critical rule: Match new with delete and new[] with delete[]. Using delete on an array (or delete[] on a single object) is undefined behaviour — may crash, may silently corrupt memory, may seem to work.

---

Common Errors

1. Memory leak

void leak() {
    int* p = new int(42);
    // forgot to delete — memory leaked
    return;     // pointer goes out of scope; memory still allocated
}

2. Dangling pointer

int* p = new int(42);
delete p;
cout << *p;     // UB — pointer no longer valid

3. Double delete

int* p = new int(42);
delete p;
delete p;       // UB — already freed

4. Wrong bracket form

int* arr = new int[10];
delete arr;     // wrong — should be delete[] arr;

5. Out-of-bounds access

int* arr = new int[5];
arr[10] = 99;   // UB — buffer overflow

---

new and delete vs malloc / free — exam classic

Aspectnew / delete (C++)malloc / free (C)
LanguageC++ operatorC function
HeaderNone (built-in)<cstdlib> / <stdlib.h>
Size calculationAutomatic (new int knows size)Manual: malloc(sizeof(int))
Return typeTyped pointer (e.g. int*)void* — needs cast
Constructor / destructorCalls constructorDoes NOT — returns raw memory
FailureThrows std::bad_allocReturns NULL
InitialisationCan use new int(42) to initReturns uninitialised memory
Array formnew[] / delete[]Same malloc/free
OverloadableYes (per-class)No
Type safetyStrongWeak (void*)

Code comparison

malloc / free:

int* p = (int*) malloc(sizeof(int));   // cast needed
if (p == NULL) { /* failed */ }
*p = 42;
free(p);

new / delete:

int* p = new int(42);   // size + init in one step
// (throws on failure)
delete p;

For classes, new does much more:

class A { public: A() { cout << "Constructor\n"; } };

A* a1 = new A();          // calls constructor
A* a2 = (A*) malloc(sizeof(A));   // does NOT call constructor

Using malloc for class objects is a bug — the object is not properly constructed.

---

Dynamic Memory for Arrays — Patterns

1. User-sized array

int n;
cout << "Enter size: ";
cin >> n;

int* arr = new int[n];     // size known only at runtime
for (int i = 0; i < n; i++) arr[i] = i * i;
for (int i = 0; i < n; i++) cout << arr[i] << " ";

delete[] arr;

2. 2D dynamic array

int rows = 3, cols = 4;

// Allocate
int** matrix = new int*[rows];
for (int i = 0; i < rows; i++) {
    matrix[i] = new int[cols];
}

// Use
for (int i = 0; i < rows; i++)
    for (int j = 0; j < cols; j++)
        matrix[i][j] = i * cols + j;

// Free — IN REVERSE ORDER
for (int i = 0; i < rows; i++) delete[] matrix[i];
delete[] matrix;

3. Array of objects

class Point {
public:
    int x, y;
    Point() : x(0), y(0) {}
};

Point* points = new Point[10];   // calls default constructor 10 times
points[0].x = 5;
points[0].y = 7;

delete[] points;                  // calls destructor 10 times

---

Modern C++ — Smart Pointers (C++11+)

Manual new/delete is error-prone. Modern C++ uses smart pointers that auto-delete:

#include <memory>

// unique_ptr — single owner; automatically deleted
auto p = make_unique<int>(42);
cout << *p;
// no delete needed — destructor handles it

// shared_ptr — multiple owners with reference count
auto s = make_shared<Student>(101);
// auto-freed when last shared_ptr is destroyed

// unique_ptr for arrays
auto arr = make_unique<int[]>(10);
arr[0] = 1;
Modern note: The IPU exam expects new/delete style. In real-world code, prefer unique_ptr/shared_ptr to eliminate memory leaks at the design level. RAII (Resource Acquisition Is Initialisation) is the C++ idiom for managing all resources.

---

Memory Leak Detection Tools

  • Valgrind (Linux/Mac) — detects leaks, uninitialised reads, invalid frees
  • AddressSanitizer (ASan) — Clang/GCC flag, run-time detection
  • Visual Studio Debugger — built-in CRT debug heap
  • Dr. Memory — Windows
  • LeakSanitizer (LSan) — part of ASan

A leaking program may "work" for a short run but exhaust memory on long-running services (servers, embedded systems).

---

new Failure Handling

Default behaviour (throws)

try {
    int* huge = new int[1000000000];   // may throw bad_alloc
} catch (bad_alloc& e) {
    cout << "Allocation failed: " << e.what();
}

nothrow variant — returns nullptr instead of throwing

int* p = new(nothrow) int[1000000000];
if (p == nullptr) cout << "Allocation failed";
else { /* use p */ delete[] p; }

---

placement new (advanced)

Allocate the object in pre-existing memory:

char buffer[sizeof(Student)];
Student* s = new (buffer) Student(101);  // constructs in 'buffer'
s->~Student();   // must manually call destructor — no delete

Used in: custom allocators, memory pools, embedded systems.

---

Study deep

  1. Memory leaks compound at scale. A single 100-byte leak in a function called once is invisible. The same leak in a server handling 10,000 requests/sec is 1 MB/sec leaked — server crashes within hours.
  1. RAII is C++'s killer feature. Java has garbage collection; C++ has RAII (objects clean up themselves on scope exit). RAII covers memory, files, locks, sockets, anything. Smart pointers are RAII for heap memory.
  1. Stack > Heap when possible. Stack allocation is essentially free (just a pointer adjustment). Heap allocation involves the allocator's internal bookkeeping. Modern advice: allocate on the stack unless you have a reason not to.
  1. new cannot be ignored even with smart pointers. Smart pointers internally use new and delete. Understanding them is essential before using smart pointers correctly.
  1. C++11 introduced make_unique / make_shared. These are preferred over new even in modern C++ — they guarantee exception safety and reduce visible memory management. The IPU syllabus doesn't cover them, but every job interview expects familiarity.

Key Terms — Lesson 1.4

The terms below cover C++ memory management — every PYQ on new/delete, dynamic allocation, or memory pitfalls expects them.

Static Memory Allocation — Memory allocated at compile time for variables whose size is known at compile time — global variables, static locals, and stack-allocated local variables of fixed size. The compiler decides the layout; the developer cannot resize.

Dynamic Memory Allocation — Memory allocated at runtime from the heap using new (in C++) or malloc (in C). The developer chooses the size at the moment of allocation. Required when the size is not known at compile time.

Stack vs Heap — Two memory regions with different lifetimes and management. The stack holds function call frames and their local variables; allocation is automatic and very fast, deallocation happens at function return. The heap holds dynamically allocated objects; allocation is explicit (new/malloc), often slower, and deallocation must also be explicit (delete/free).

new Operator — The C++ operator that allocates memory on the heap, runs the constructor, and returns a typed pointer. int* p = new int(5); allocates an int initialised to 5. new throws std::bad_alloc on failure (or returns null with new(nothrow)).

delete Operator — The C++ operator that runs the destructor and deallocates heap memory previously allocated by new. delete p; deletes a single object; delete[] arr; deletes an array. Calling the wrong form is undefined behaviour.

new[] and delete[] — The array forms of new and delete. int* arr = new int[10]; allocates an array of 10 ints; delete[] arr; deallocates it. Mixing new with delete[] or new[] with delete is undefined behaviour — one of the classic C++ traps.

malloc / free — The C memory-management functions. malloc(size) allocates a raw byte block and returns void*; free(p) releases it. They do not call constructors or destructors — using them for C++ objects skips initialisation and cleanup. Only use malloc/free for primitive types or interoperability with C code.

Constructor Call (by new) — When new allocates an object, it automatically calls the constructor to initialise the object's state. This is the main reason to use new over malloc for C++ classes.

Destructor Call (by delete) — When delete deallocates an object, it automatically calls the destructor to clean up the object's resources (close files, release locks, free owned memory) before releasing the memory itself.

Memory Leak — A bug where dynamically allocated memory is not deallocated when no longer needed. Each leak permanently consumes a small amount of memory; over time leaks can exhaust available memory and crash the process. Tools: Valgrind, AddressSanitizer (ASan).

Dangling Pointer — A pointer that still holds the address of memory that has been deallocated. Dereferencing a dangling pointer is undefined behaviour — may crash, may read garbage, may corrupt unrelated data. Best practice: set pointers to nullptr after delete.

Double Free — Calling delete (or free) twice on the same pointer. Undefined behaviour — may crash, may corrupt the heap. Modern C++ smart pointers (std::unique_ptr, std::shared_ptr) make double free impossible.

nullptr (C++11) — The typed null-pointer constant in modern C++, replacing the older NULL macro. nullptr has type std::nullptr_t, which converts to any pointer type but never to integer. Resolves ambiguities that NULL (#defined to 0) caused with function overloading.

Heap Fragmentation — When repeated allocation and deallocation of varying-sized blocks leave the heap with many small free regions interspersed with allocated blocks, so that a large new allocation may fail even when the total free memory is sufficient. Long-running C++ services use pool allocators or arena allocators to mitigate fragmentation.

Smart Pointer (C++11) — A class template that wraps a raw pointer and manages its lifetime automatically via RAII. std::unique_ptr<T> owns the pointee exclusively and deletes it when the unique_ptr goes out of scope. std::shared_ptr<T> allows shared ownership via reference counting. std::weak_ptr<T> is a non-owning observer. Smart pointers eliminate most manual delete calls in modern C++.

make_unique / make_shared (C++14 / C++11) — Factory functions that construct an object on the heap and return a smart pointer: auto p = std::make_unique<MyClass>(args);. Preferred over raw new because they're exception-safe and require no manual delete.

RAII (Resource Acquisition Is Initialisation) — Bjarne Stroustrup's idiom for tying resource lifetimes to object lifetimes. The constructor acquires the resource (memory, file handle, lock); the destructor releases it. RAII makes resource management automatic and exception-safe and underlies the entire smart-pointer family.

Free Store / Heap — Two near-synonymous terms for the dynamically-allocated memory region. Strictly, "heap" is C terminology, "free store" is C++ terminology; in practice they refer to the same region.

std::bad_alloc — The exception type that new throws when memory allocation fails. Modern C++ programs catch std::bad_alloc if they want to handle out-of-memory gracefully; otherwise it propagates and terminates the program.

new (nothrow) — A variant of new that returns nullptr on failure instead of throwing std::bad_alloc. Used in code that prefers C-style error handling over exceptions.

Placement new — A specialised form of new that constructs an object at a specified memory address without allocating. Used for memory pools, in-place reconstruction, and embedded systems where the developer manages the memory layout manually.

Valgrind / AddressSanitizer (ASan) — Tools that detect memory bugs at runtime — leaks, double-frees, use-after-free, out-of-bounds reads/writes. Valgrind runs the program in a virtualised environment; AddressSanitizer is a compiler instrumentation (GCC/Clang) that's faster than Valgrind and now the industry default for memory bug detection.

---

PYQ pattern (very common): "Differentiate new / delete and malloc / free." — Tabulate 6-8 differences (language, size calc, return type, ctor/dtor, failure, type safety). Show code comparison.
PYQ pattern: "Write a C++ program using new to dynamically allocate memory for an array of integers, take input from user and display sum." — Use new int[n], loop input, loop sum, delete[].
PYQ pattern: "What is dynamic memory allocation? Explain with example." — Define heap allocation; use case (size unknown at compile time); show new/delete example; mention need to free to avoid leaks.