DeveloperBreeze

Overview

C++ developers often face memory management headaches, especially when working on legacy systems that don’t use C++11 or newer. Smart pointers like std::unique_ptr and std::shared_ptr are powerful, but what if you’re stuck with raw pointers?

In this tutorial, you'll learn:

  • How memory leaks happen.
  • How to structure your code to avoid them.
  • A design pattern to manage dynamic memory safely (RAII without smart pointers).
  • A reusable ScopedPointer class to emulate unique_ptr in old C++.

The Problem: Memory Leaks from Raw Pointers

Consider this code:

void loadData() {
    char* buffer = new char[1024];
    // some processing...
    if (someCondition()) {
        return; // leak!
    }
    delete[] buffer;
}

What’s wrong? If someCondition() returns true, buffer is never deallocated.


Solution 1: Manual try/catch + delete (not scalable)

void loadData() {
    char* buffer = new char[1024];
    try {
        if (someCondition()) {
            throw std::runtime_error("Something went wrong");
        }
        // more code...
    } catch (...) {
        delete[] buffer;
        throw;
    }
    delete[] buffer;
}

Not elegant. Easy to forget or misplace deletes. Let's go better.


Solution 2: Use RAII Even Without Smart Pointers

RAII (Resource Acquisition Is Initialization) is a pattern where resource allocation is tied to object lifetime. When an object goes out of scope, its destructor cleans up.

Let’s build a small ScopedPointer class.


ScopedPointer.h

template <typename T>
class ScopedPointer {
private:
    T* ptr;

public:
    explicit ScopedPointer(T* p = nullptr) : ptr(p) {}

    ~ScopedPointer() {
        delete ptr;
    }

    T& operator*() const { return *ptr; }
    T* operator->() const { return ptr; }
    T* get() const { return ptr; }

    void reset(T* p = nullptr) {
        if (ptr != p) {
            delete ptr;
            ptr = p;
        }
    }

    // Prevent copy
    ScopedPointer(const ScopedPointer&) = delete;
    ScopedPointer& operator=(const ScopedPointer&) = delete;
};

For arrays:

template <typename T>
class ScopedArray {
private:
    T* ptr;

public:
    explicit ScopedArray(T* p = nullptr) : ptr(p) {}

    ~ScopedArray() {
        delete[] ptr;
    }

    T& operator[](int index) const { return ptr[index]; }
    T* get() const { return ptr; }

    void reset(T* p = nullptr) {
        if (ptr != p) {
            delete[] ptr;
            ptr = p;
        }
    }

    // Prevent copy
    ScopedArray(const ScopedArray&) = delete;
    ScopedArray& operator=(const ScopedArray&) = delete;
};

Usage

#include "ScopedPointer.h"

void loadData() {
    ScopedArray<char> buffer(new char[1024]);

    if (someCondition()) {
        return; // no memory leak!
    }

    // buffer is auto-deleted when going out of scope
}

Bonus: Integrating with Legacy C APIs

Some legacy APIs require raw pointers. You can still use get():

void legacyFunction(char* data);

void useLegacyAPI() {
    ScopedArray<char> buffer(new char[512]);
    legacyFunction(buffer.get());
}

Conclusion

Even without smart pointers, you can manage memory safely in C++ using the RAII pattern. This approach:

  • Prevents memory leaks.
  • Simplifies exception handling.
  • Keeps your code clean and maintainable.

In newer projects, always prefer std::unique_ptr and std::shared_ptr. But in legacy systems, RAII with simple wrappers like ScopedPointer can save you.

Continue Reading

Discover more amazing content handpicked just for you

Tutorial

Deep Copy in C++: How to Avoid Shallow Copy Pitfalls

This is the Rule of Five. Add move semantics if your class is performance-sensitive and uses resource ownership.

When your class uses raw pointers:

Apr 11, 2025
Read More
Tutorial

Implementing a Domain-Specific Language (DSL) with LLVM and C++

Main Entry Point: main.cpp

#include "DSL/Lexer.h"
#include "DSL/Parser.h"
#include "DSL/AST.h"
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/Support/TargetSelect.h>
#include <iostream>
#include <memory>

extern llvm::Function* generateFunction(llvm::LLVMContext& context, llvm::Module& module, ASTNode* root);
extern void optimizeModule(llvm::Module& module);

int main() {
    // Initialize LLVM.
    llvm::InitializeNativeTarget();
    llvm::InitializeNativeTargetAsmPrinter();
    llvm::LLVMContext context;
    llvm::Module module("MyDSLModule", context);

    std::string input;
    std::cout << "Enter an expression: ";
    std::getline(std::cin, input);

    Lexer lexer(input);
    Parser parser(lexer);
    std::unique_ptr<ASTNode> astRoot;
    try {
        astRoot = parser.parseExpression();
    } catch (const std::exception& ex) {
        std::cerr << "Parsing error: " << ex.what() << std::endl;
        return 1;
    }

    llvm::Function* func = generateFunction(context, module, astRoot.get());
    if (!func) {
        std::cerr << "Failed to generate LLVM function." << std::endl;
        return 1;
    }

    optimizeModule(module);

    // For demonstration, print the LLVM IR.
    module.print(llvm::outs(), nullptr);

    // In a full implementation, you could now JIT compile and execute the function.
    return 0;
}

Feb 12, 2025
Read More
Tutorial
csharp

Developing a Real-Time Multiplayer Game with Unity and C#

For this tutorial, we'll focus on using "Netcode for GameObjects," which is Unity's official solution for networking.

  • In the Hierarchy window, right-click and create a new 3D Object > Plane to serve as the ground.
  • Create a 3D Object > Cube to act as the player character.
  • Position the cube above the plane so that it is ready to fall due to gravity.
  • Add a Camera and Light to the scene if they are not already present.

Aug 14, 2024
Read More
Code
csharp

Unity Inventory System using Scriptable Objects

  • Data Management: Scriptable objects allow you to manage item data independently from game logic, making it easier to update and maintain.
  • Reusability: You can create item templates and reuse them across different scenes and projects.
  • Performance: Scriptable objects reduce memory overhead compared to prefab-based systems since they are shared across instances.

Aug 12, 2024
Read More
Code
csharp

Unity Player Controller Blueprint

No preview available for this content.

Aug 12, 2024
Read More
Code
csharp

Calculate Sum of Numbers in Array

No preview available for this content.

Jan 26, 2024
Read More

Discussion 0

Please sign in to join the discussion.

No comments yet. Start the discussion!