SyntaxStudy
Sign Up
C++ Stack vs Heap and RAII
C++ Beginner 1 min read

Stack vs Heap and RAII

C++ programs have two primary memory regions for objects: the stack and the heap (free store). Stack allocation is automatic — objects are created when their declaration is reached and destroyed when they leave scope. Stack allocation is extremely fast (a single register increment) and requires no explicit cleanup, but the stack is limited in size and cannot hold objects whose lifetime must exceed their declaring scope. Heap allocation via 'new' creates objects with dynamic lifetime that persist until explicitly destroyed with 'delete'. The programmer is responsible for matching every 'new' with a 'delete' and every 'new[]' with a 'delete[]'. Failing to do so causes memory leaks; calling 'delete' twice causes undefined behaviour. Raw 'new'/ 'delete' are therefore best avoided in modern C++. RAII (Resource Acquisition Is Initialisation) is the C++ idiom that ties resource ownership to object lifetime. An object acquires a resource in its constructor and releases it in its destructor. Because destructors run deterministically when objects leave scope — even during stack unwinding after an exception — RAII guarantees leak-free cleanup without explicit try/finally blocks. Smart pointers, file-stream objects, and lock guards are all RAII wrappers.
Example
#include <iostream>
#include <fstream>
#include <stdexcept>

// RAII file wrapper
class FileHandle {
public:
    explicit FileHandle(const char* path, const char* mode) {
        file_ = std::fopen(path, mode);
        if (!file_) throw std::runtime_error("Cannot open file");
        std::cout << "File opened\n";
    }

    ~FileHandle() {
        if (file_) {
            std::fclose(file_);
            std::cout << "File closed\n";  // always runs
        }
    }

    // Prevent copy
    FileHandle(const FileHandle&)            = delete;
    FileHandle& operator=(const FileHandle&) = delete;

    FILE* get() const { return file_; }

private:
    FILE* file_;
};

// RAII mutex simulation
struct MutexLock {
    explicit MutexLock(bool& mutex) : mutex_(mutex) {
        mutex_ = true;
        std::cout << "Lock acquired\n";
    }
    ~MutexLock() {
        mutex_ = false;
        std::cout << "Lock released\n";
    }
    bool& mutex_;
};

int main() {
    bool mutex = false;

    {
        MutexLock lock(mutex);
        std::cout << "Critical section\n";
        // lock released automatically at end of block
    }

    // FileHandle example (file may not exist in demo)
    try {
        FileHandle fh("demo.txt", "w");
        std::fputs("Hello RAII\n", fh.get());
        // file closed automatically even if exception thrown
    } catch (const std::exception& e) {
        std::cout << "Error: " << e.what() << "\n";
    }

    return 0;
}