C++ Heap Corruption: Double Free, Wrong delete[], and Detection
이 글의 핵심
Practical guide to heap corruption: causes, tools, and prevention.
What is heap corruption?
Damage to heap bookkeeping or adjacent memory, often from out-of-bounds writes or invalid free/delete.
int* arr = new int[10];
arr[10] = 42; // out of bounds
delete[] arr;
Common causes
int* arr = new int[10];
arr[15] = 42;
int* ptr = new int(10);
delete ptr;
delete ptr;
int* arr = new int[10];
delete arr; // should be delete[]
int* ptr = new int(10);
delete ptr;
*ptr = 42;
Examples
Example 1: Buffer overflow on the heap
#include <iostream>
#include <cstring>
void bufferOverflow() {
char* buffer = new char[10];
strcpy(buffer, "This is too long");
delete[] buffer;
}
void safeBuffer() {
char* buffer = new char[20];
strncpy(buffer, "This is safe", 19);
buffer[19] = '\0';
delete[] buffer;
}
void useString() {
std::string str = "This is safe";
}
Example 2: Double free
#include <memory>
void doubleFree() {
int* ptr = new int(10);
delete ptr;
delete ptr;
}
void safeFree() {
int* ptr = new int(10);
delete ptr;
ptr = nullptr;
delete ptr;
}
void smartPointer() {
auto ptr = std::make_unique<int>(10);
}
Example 3: Wrong delete
void wrongDelete() {
int* arr = new int[10];
delete arr;
}
void correctDelete() {
int* arr = new int[10];
delete[] arr;
int* ptr = new int(10);
delete ptr;
}
void smartPointer() {
auto arr = std::make_unique<int[]>(10);
auto ptr = std::make_unique<int>(10);
}
Example 4: Use-after-free
#include <iostream>
void useAfterFree() {
int* ptr = new int(10);
delete ptr;
std::cout << *ptr << std::endl;
}
void safeUse() {
int* ptr = new int(10);
std::cout << *ptr << std::endl;
delete ptr;
}
void smartPointer() {
auto ptr = std::make_unique<int>(10);
std::cout << *ptr << std::endl;
}
Detection
// ASan: g++ -fsanitize=address -g program.cpp
// Valgrind: valgrind --tool=memcheck ./program
Common pitfalls
Pitfall 1: Off-by-one loops
int* arr = new int[10];
for (int i = 0; i < 10; i++) {
arr[i] = i;
}
delete[] arr;
std::vector<int> vec(10);
Pitfall 2: Mixing new and realloc
std::vector<int> vec(10);
vec.resize(20);
Pitfall 3: Pointer arithmetic out of range
int* arr = new int[10];
if (index < 10) {
arr[index] = 42;
}
delete[] arr;
Pitfall 4: Struct members not freed
struct Node {
int* data;
Node* next;
};
void deleteNode(Node* node) {
delete[] node->data;
delete node;
}
struct NodeSafe {
std::unique_ptr<int[]> data;
std::unique_ptr<NodeSafe> next;
};
Prevention
auto ptr = std::make_unique<int>(10);
auto arr = std::make_unique<int[]>(10);
std::vector<int> vec(10);
Debugging tools
g++ -fsanitize=address -g program.cpp
./a.out
valgrind --leak-check=full --show-leak-kinds=all ./program
FAQ
Q1: When does heap corruption happen?
A: Overflows, double free, wrong delete form, UAF.
Q2: Detection?
A: ASan, Valgrind, debug heap (platform-specific).
Q3: Prevention?
A: Smart pointers, containers, RAII.
Q4: Symptoms?
A: Crashes, flaky behavior, corruption far from the bug.
Q5: delete vs delete[]?
A: delete for single object; delete[] for new[] arrays.
Q6: Resources?
A: Effective C++, ASan docs, Valgrind docs.
See also
- C++ use-after-free
- C++ memory leak
- C++ sanitizers
Practical tips
Debugging
- Warnings first
- Small repro
Performance
- Profile first
Code review
- Conventions
Checklist
Before coding
- Right approach?
- Maintainable?
- Performance?
While coding
- Warnings?
- Edge cases?
- Errors?
At review
- Clear?
- Tests?
- Docs?
Keywords
C++, heap corruption, heap, memory, debugging, ASan.
Related posts
- C++ memory leak
- C++ sanitizers
- C++ use-after-free
- C++ Valgrind
- C++ algorithm heap