Memory Management in C++

Bikram Sarkar
3 min read1 day ago
Photo by Liam Briese on Unsplash

In C++, there are 2 ways memory can be managed, using automatic memory management via smart pointers which is generally preferable and other one is through manual memory management. Automatic memory management approach reduces the risk of common errors like memory leaks, double deletions, and dangling pointers, and simplifies resource management.

Manual Memory Management

In manual memory management, you explicitly allocate and deallocate memory

#include <iostream>

void manualMemoryManagement() {
int* ptr = new int; // Allocate memory for an int
*ptr = 10;
std::cout << "Value: " << *ptr << std::endl;
delete ptr; // Deallocate the memory

int* arr = new int[10]; // Allocate memory for an array of 10 ints
for (int i = 0; i < 10; ++i) {
arr[i] = i;
}
delete[] arr; // Deallocate the array
}

Risks:

Memory Leaks: Forgetting to call delete leads to memory leaks.

Double Deletion: Accidentally calling delete twice on the same pointer leads to undefined behavior.

Dangling Pointers: Accessing memory after it has been deleted leads to undefined behavior.

Automatic Memory Management

With automatic memory management using smart pointers, the allocation and deallocation of memory are handled automatically

#include <iostream>
#include <memory> // For std::unique_ptr and std::shared_ptr

void automaticMemoryManagement() {
{
std::unique_ptr<int> ptr = std::make_unique<int>(10); // Automatically managed memory
std::cout << "Value: " << *ptr << std::endl;
// ptr is automatically destroyed when it goes out of scope, releasing the memory
}

{
std::shared_ptr<int> sptr1 = std::make_shared<int>(20); // Shared ownership
std::shared_ptr<int> sptr2 = sptr1; // Shared ownership, reference count increased
std::cout << "Value: " << *sptr1 << std::endl;
// Memory is automatically managed and deallocated when the last reference goes out of scope
}
}

Benefits:

Automatic Cleanup: Memory is automatically released when the smart pointer goes out of scope.

No Memory Leaks: Smart pointers ensure that memory is freed, reducing the risk of memory leaks.

No Double Deletion: The smart pointer ensures that delete is called only once.

Shared Ownership: std::shared_ptr allows multiple pointers to manage the same resource, automatically deallocating it when the last std::shared_ptr goes out of scope.

Comparison Example

Where manual memory management can go wrong versus using smart pointers

Manual Memory Management:

#include <iostream>

void manualExample() {
int* a = new int(5);
int* b = a; // Both pointers now point to the same memory

delete a; // Memory is deallocated
// delete b; // Uncommenting this line would lead to undefined behavior (double deletion)

// Memory leak if we forget to delete 'a' or 'b'
// Dangling pointer: 'b' is now a dangling pointer after 'a' is deleted
}

Automatic Memory Management:

#include <iostream>
#include <memory>

void automaticExample() {
{
std::shared_ptr<int> a = std::make_shared<int>(5);
std::shared_ptr<int> b = a; // Shared ownership

// Memory is automatically deallocated when the last shared_ptr (a or b) goes out of scope
} // No risk of memory leaks, double deletions, or dangling pointers
}

Conclusion

Using automatic memory management with smart pointers is generally better in C++ for several reasons

Safety: Reduces the risk of memory management errors.

Simplicity: Simplifies code by automating resource management.

Maintainability: Makes code easier to maintain and understand.

By leveraging smart pointers (std::unique_ptr and std::shared_ptr), we can write more robust and reliable C++ programs with fewer memory-related issues.

--

--