Fundamentals 34 min read

How Does delete Know Memory Size? A Deep Dive into C++ Memory Management

This article explains C++ memory management fundamentals, detailing how delete and free release memory without explicit size knowledge, the role of stack, heap, data and code segments, differences between new/delete and malloc/free, array handling, common pitfalls, and interview questions with code examples.

Deepin Linux
Deepin Linux
Deepin Linux
How Does delete Know Memory Size? A Deep Dive into C++ Memory Management

In the world of C++ programming, memory management is an unavoidable key topic. When we use the delete keyword to free memory, a puzzling question arises: delete does not know the size of the memory it operates on, so how does it accurately release the memory?

1. Basics of Memory Management

1.1 Program Memory Area Division

Before analyzing the delete memory release mechanism, it is necessary to understand the runtime memory region layout of a C++ program. Typically, a running C++ program’s memory space is divided into the following key regions:

Stack (Stack): automatically allocated and freed by the compiler, storing function parameters, local variables, etc. It has high allocation and deallocation efficiency, operating like a LIFO stack.

Heap (Heap): generally allocated and freed manually by the programmer, used for dynamically allocated objects and data. It is flexible but prone to memory leaks if not freed properly.

Data Segment: stores initialized global and static variables. It includes the initialized data segment and the uninitialized (BSS) segment.

Code Segment: stores the binary code of functions, usually read‑only.

The heap region is the main target of delete, and understanding these regions helps clarify delete ’s role.

1.2 C++ Memory Management Methods

C++ provides two main memory management approaches: the C‑style malloc / free and the C++‑specific new / delete.

malloc/free allocate and release memory from the heap without invoking constructors or destructors. Example:

int* p = (int*)malloc(sizeof(int));
if (p != nullptr) {
    *p = 10; // manual assignment
}
free(p);
p = nullptr; // avoid dangling pointer

new/delete allocate memory and automatically call constructors and destructors. Example of a custom class:

class MyClass {
public:
    MyClass() { std::cout << "MyClass constructor" << std::endl; }
    ~MyClass() { std::cout << "MyClass destructor" << std::endl; }
};
MyClass* obj = new MyClass; // allocation and construction
delete obj; // destructor then deallocation

For arrays, new[] must be paired with delete[] to ensure each element’s destructor is called.

1.3 Heap Classification and Management (glibc)

glibc divides the heap into two categories: the main arena heap (obtained via brk) and sub‑arena heaps (obtained via mmap). The main arena grows upward in the process address space, while sub‑arenas are linked together and can be created per thread.

Heap allocation in the main arena expands the program break; sub‑arena allocation uses mmap and may create multiple independent heaps.

Heap release for the main arena may shrink the break when the top chunk is sufficiently free; sub‑arena heaps are returned to the kernel with munmap when completely freed.

1.4 glibc Heap Allocation Logic

When malloc is called, the allocator first searches the thread’s arena for a suitable free block. If none is found, it may split the top chunk or request more memory via brk or mmap depending on the requested size.

1.5 malloc Function

malloc

allocates a contiguous block of the requested size and returns a void* pointer. The caller must cast it to the appropriate type.

1.6 free Function

free

marks the block as free, possibly merging it with adjacent free blocks to reduce fragmentation.

2. delete Memory Release Mechanism

2.1 Basic Usage of delete

For a single object allocated with new, delete calls the destructor and then releases the memory.

#include <iostream>
int main() {
    int* ptr = new int;
    *ptr = 10;
    std::cout << "The value of ptr is: " << *ptr << std::endl;
    delete ptr;
    return 0;
}

2.2 delete for Arrays (delete[])

When an array is allocated with new[], delete[] reads the hidden size stored before the array data, calls each element’s destructor, and then frees the whole block.

#include <iostream>
int main() {
    int* arr = new int[5];
    for (int i = 0; i < 5; ++i) arr[i] = i + 1;
    delete[] arr;
    return 0;
}

2.3 delete for Simple Types

For simple types like int, delete essentially forwards to free because no destructor work is needed.

int* p = new int;
*p = 10;
delete p; // equivalent to free(p)

2.4 delete for Complex Types

For user‑defined classes, delete first invokes the destructor, which may release resources, and then calls the deallocation function.

class MyClass {
public:
    MyClass() { data = new int[10]; std::cout << "MyClass constructor" << std::endl; }
    ~MyClass() { delete[] data; std::cout << "MyClass destructor" << std::endl; }
private:
    int* data;
};
MyClass* obj = new MyClass;
delete obj; // destructor then memory release

2.5 delete[] Size Retrieval

When new[] allocates an array, it stores the element count (typically 4 bytes) just before the first element. delete[] reads this count to know how many destructors to call.

3. Common Problems and Solutions

3.1 Memory Leaks

Forgetting to call delete after new leads to leaks. Using smart pointers such as std::unique_ptr automates destruction.

#include <memory>
void properMemoryManagement() {
    std::unique_ptr<int> ptr = std::make_unique<int>();
    // no manual delete needed
}

3.2 Dangling Pointers

After freeing memory, set the pointer to nullptr to avoid undefined behavior.

int* ptr = new int;
delete ptr;
ptr = nullptr;

3.3 Mismatched delete/delete[]

Using delete on memory allocated with new[] (or vice‑versa) results in undefined behavior and possible leaks.

3.4 Double Free

Calling delete twice on the same pointer is erroneous. Setting the pointer to nullptr after deletion prevents this.

4. Interview Questions

The article concludes with a series of interview questions covering how delete determines size, the necessity of delete[] for arrays, differences between new/delete and malloc/free, and best practices for safe memory management.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Memory ManagementCHeapmallocallocationFreeDELETEnew
Deepin Linux
Written by

Deepin Linux

Research areas: Windows & Linux platforms, C/C++ backend development, embedded systems and Linux kernel, etc.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.