Skip to content

new/delete — The Dangerous Way

newdelete là cách thủ công để cấp phát bộ nhớ. Chúng nguy hiểm và nên tránh trong Modern C++.

Analogy: Mượn tiền không trả

┌─────────────────────────────────────────────────────────────────┐
│                    BORROWING MONEY ANALOGY                       │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   new = Mượn tiền từ ngân hàng (Heap)                          │
│   delete = Trả tiền lại                                         │
│                                                                 │
│   😰 MEMORY LEAK = Mượn xong quên trả                          │
│       → Ngân hàng hết tiền cho vay (RAM hết)                    │
│                                                                 │
│   😱 DOUBLE FREE = Trả 2 lần cùng 1 khoản                      │
│       → Ngân hàng confused, database corrupted                  │
│                                                                 │
│   💀 DANGLING POINTER = Cầm receipt của khoản đã trả           │
│       → Dùng receipt cũ = undefined behavior                    │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Basic new/delete

cpp
// Allocate single object
int* ptr = new int;      // Allocate
*ptr = 42;               // Use
delete ptr;              // Free

// Allocate array
int* arr = new int[100]; // Allocate 100 ints
arr[0] = 1;              // Use
delete[] arr;            // Free array (note the [])

The Problems

1. Memory Leak

cpp
void memoryLeak() {
    int* ptr = new int(42);
    
    // Oops! Forgot to delete
    // ptr goes out of scope, memory is LOST forever
}

// Each call leaks 4 bytes
// Call 1 million times = 4MB leaked!

2. Leak on Exception

cpp
void leakOnException() {
    int* ptr = new int(42);
    
    doSomething();  // If this throws exception...
    
    delete ptr;     // This line NEVER executes!
}

3. Double Free

cpp
void doubleFree() {
    int* ptr = new int(42);
    delete ptr;
    
    // ... later, forgot we deleted ...
    
    delete ptr;  // 💥 UNDEFINED BEHAVIOR!
}

4. Dangling Pointer

cpp
int* danglingPointer() {
    int* ptr = new int(42);
    int* copy = ptr;
    
    delete ptr;
    
    // copy still points to freed memory!
    return copy;  // 💀 Returning garbage
}

void useDangling() {
    int* bad = danglingPointer();
    *bad = 10;  // 💥 Writing to freed memory!
}

Error Examples

cpp
// ❌ Memory leak - forgot delete
void bad1() {
    int* p = new int[1000];
    // return without delete
}

// ❌ Wrong delete type
void bad2() {
    int* arr = new int[100];
    delete arr;    // Should be delete[]!
}

// ❌ Delete stack memory
void bad3() {
    int x = 10;
    int* p = &x;
    delete p;      // 💥 x is on STACK, not heap!
}

// ❌ Use after delete
void bad4() {
    int* p = new int(42);
    delete p;
    std::cout << *p;  // 💥 Undefined behavior!
}

Trying to Fix It (Still Bad)

cpp
void tryingToBeCareful() {
    int* ptr = new int(42);
    
    try {
        doRiskyOperation();
        delete ptr;
    } catch (...) {
        delete ptr;  // Duplicate code!
        throw;
    }
}

Vấn đề: Phải nhớ delete ở MỌI đường code path!


Statistics

┌─────────────────────────────────────────────────────────────────┐
│                    MEMORY BUG STATISTICS                         │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   📊 Microsoft: 70% of CVEs are memory safety issues            │
│   📊 Chrome: 70% of serious security bugs are memory bugs       │
│   📊 Firefox: Similar statistics                                │
│                                                                 │
│   Most common:                                                  │
│   • Use-after-free                                              │
│   • Buffer overflow                                             │
│   • Uninitialized memory                                        │
│                                                                 │
│   💡 Solution: Don't use raw new/delete!                        │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

When is new/delete OK?

⚠️ RARE CASES

Chỉ dùng new/delete trực tiếp khi:

  • Implementing custom containers/allocators
  • Interfacing with C libraries
  • Extreme performance optimization

Cho 99% code, KHÔNG BAO GIỜ dùng raw new/delete!


📚 Tổng kết

ProblemDescription
Memory LeakQuên delete → RAM exhausted
Double FreeDelete 2 lần → Corruption
Dangling PointerDùng sau khi delete → UB
Exception UnsafeException = leak

➡️ Tiếp theo

Giải pháp cho tất cả vấn đề trên: RAII

RAII → — The heart of C++.