Production-grade skill for safe and efficient C++ memory management. Covers RAII, smart pointers, custom allocators, memory pools, and leak detection techniques.
Production-grade C++ memory management guidance covering RAII, smart pointers, custom allocators, and leak detection. Use when writing or reviewing C++ code that involves dynamic allocation, resource handling, or memory safety concerns.
/plugin marketplace add pluginagentmarketplace/custom-plugin-cpp/plugin install cpp@pluginagentmarketplace-cppThis skill inherits all available tools. When active, it can use any tool Claude has access to.
assets/memory_config.yamlreferences/MEMORY_GUIDE.mdscripts/leak_detector.pyProduction-Grade Learning Skill | Safe Resource Handling
Master C++ memory management for safe, efficient, and leak-free code.
Resource Acquisition Is Initialization
// ─────────────────────────────────────────────────────
// RAII wrapper for file handles
// ─────────────────────────────────────────────────────
class FileHandle {
FILE* handle_{nullptr};
public:
explicit FileHandle(const char* path, const char* mode)
: handle_(fopen(path, mode))
{
if (!handle_) {
throw std::runtime_error("Failed to open file");
}
}
~FileHandle() {
if (handle_) fclose(handle_);
}
// Non-copyable
FileHandle(const FileHandle&) = delete;
FileHandle& operator=(const FileHandle&) = delete;
// Movable
FileHandle(FileHandle&& other) noexcept
: handle_(std::exchange(other.handle_, nullptr)) {}
FileHandle& operator=(FileHandle&& other) noexcept {
if (this != &other) {
if (handle_) fclose(handle_);
handle_ = std::exchange(other.handle_, nullptr);
}
return *this;
}
FILE* get() const { return handle_; }
};
// Usage: automatic cleanup guaranteed
void processFile(const char* path) {
FileHandle file(path, "r"); // Acquired
// ... use file ...
} // Automatically closed, even if exception thrown
┌─────────────────────────────────────────────────────────────────┐
│ std::unique_ptr │ Exclusive ownership (default choice) │
│ std::shared_ptr │ Shared ownership (reference counted) │
│ std::weak_ptr │ Non-owning observer (breaks cycles) │
└─────────────────────────────────────────────────────────────────┘
// Creation (ALWAYS use make_unique)
auto widget = std::make_unique<Widget>(arg1, arg2);
// Array version
auto arr = std::make_unique<int[]>(100);
// Custom deleter
auto file = std::unique_ptr<FILE, decltype(&fclose)>(
fopen("data.txt", "r"), &fclose
);
// Transfer ownership
void takeOwnership(std::unique_ptr<Widget> w);
takeOwnership(std::move(widget)); // Explicit move required
// Creation
auto shared = std::make_shared<Resource>(); // Single allocation!
// Copy = increment reference count
auto copy = shared; // ref_count: 2
// Custom deleter
auto custom = std::shared_ptr<Database>(
new Database(),
[](Database* db) {
db->close();
delete db;
}
);
class Node {
public:
std::shared_ptr<Node> next;
std::weak_ptr<Node> prev; // Weak to prevent cycle
};
// Safe access through lock()
void useWeakPtr(std::weak_ptr<Resource> weak) {
if (auto shared = weak.lock()) { // Returns shared_ptr or nullptr
shared->doSomething();
}
}
| Problem | Detection | Solution |
|---|---|---|
| Memory leak | Valgrind, ASan | Use smart pointers |
| Dangling pointer | ASan | weak_ptr, proper lifetime |
| Double free | ASan | unique_ptr ownership |
| Buffer overflow | ASan | std::vector, std::span |
| Use after free | ASan | RAII, smart pointers |
# Valgrind (runtime)
valgrind --leak-check=full --show-leak-kinds=all ./program
# AddressSanitizer (compile-time instrumentation)
g++ -fsanitize=address -fno-omit-frame-pointer -g program.cpp
// ❌ BAD: Raw pointer ownership unclear
Widget* createWidget() {
return new Widget(); // Who deletes this?
}
// ✅ GOOD: Ownership explicit
std::unique_ptr<Widget> createWidget() {
return std::make_unique<Widget>();
}
// ❌ BAD: Exception unsafe
void process() {
Resource* r = new Resource();
doSomething(); // May throw!
delete r; // Never reached if exception
}
// ✅ GOOD: Exception safe
void process() {
auto r = std::make_unique<Resource>();
doSomething(); // Even if throws, r is deleted
}
template<typename T, size_t BlockSize = 4096>
class PoolAllocator {
struct Block {
std::array<std::byte, sizeof(T)> data;
Block* next;
};
Block* freeList_{nullptr};
std::vector<std::unique_ptr<Block[]>> blocks_;
public:
T* allocate() {
if (!freeList_) {
allocateBlock();
}
Block* block = freeList_;
freeList_ = block->next;
return reinterpret_cast<T*>(&block->data);
}
void deallocate(T* ptr) {
Block* block = reinterpret_cast<Block*>(ptr);
block->next = freeList_;
freeList_ = block;
}
private:
void allocateBlock() {
constexpr size_t count = BlockSize / sizeof(Block);
auto newBlocks = std::make_unique<Block[]>(count);
for (size_t i = 0; i < count - 1; ++i) {
newBlocks[i].next = &newBlocks[i + 1];
}
newBlocks[count - 1].next = freeList_;
freeList_ = &newBlocks[0];
blocks_.push_back(std::move(newBlocks));
}
};
Memory issue?
├── Leak suspected
│ ├── Run Valgrind → Shows "definitely lost"
│ ├── Check for raw `new` → Replace with make_unique
│ └── Check cyclic references → Use weak_ptr
├── Crash/Corruption
│ ├── Segfault at nullptr → Add null checks
│ ├── Double free → Ensure single owner (unique_ptr)
│ └── Use after free → Check object lifetime
└── Performance
├── Too many allocations → Use pool allocator
├── Fragmentation → Use arena allocator
└── False sharing → Align to cache line
#include <gtest/gtest.h>
#include <memory>
TEST(SmartPointerTest, UniquePtrOwnership) {
auto ptr = std::make_unique<int>(42);
EXPECT_NE(ptr, nullptr);
EXPECT_EQ(*ptr, 42);
auto ptr2 = std::move(ptr);
EXPECT_EQ(ptr, nullptr); // Ownership transferred
EXPECT_EQ(*ptr2, 42);
}
TEST(SmartPointerTest, SharedPtrRefCount) {
auto shared1 = std::make_shared<int>(100);
EXPECT_EQ(shared1.use_count(), 1);
auto shared2 = shared1;
EXPECT_EQ(shared1.use_count(), 2);
}
TEST(SmartPointerTest, WeakPtrExpired) {
std::weak_ptr<int> weak;
{
auto shared = std::make_shared<int>(42);
weak = shared;
EXPECT_FALSE(weak.expired());
}
EXPECT_TRUE(weak.expired());
}
C++ Plugin v3.0.0 - Production-Grade Learning Skill
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.