You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

栈组(SetOfStacks)实现的内存泄漏检测与动态内存管理最佳实践

Hi there! Let's break down your questions about memory leak detection, dynamic memory management best practices, and also spot some issues in your SetOfStacks implementation.

高效检测内存泄漏的方法

Here are the most practical tools and techniques to catch memory leaks:

  • Valgrind (Memcheck): A go-to tool for Linux and macOS. Compile your code with -g for debug symbols, then run valgrind --leak-check=full ./your_program. It will report exactly where leaked memory was allocated and not freed.
  • AddressSanitizer (ASAN): Integrated into Clang and GCC. Compile with -fsanitize=address -g—it runs alongside your program, detects leaks (and other memory issues like buffer overflows) in real time, and gives detailed error messages.
  • Visual Studio Memory Leak Detector: On Windows, enable it by including <crtdbg.h> and adding _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); at the start of main(). It will print leak reports when your program exits.
  • Custom Tracking (Last Resort): Overload operator new and operator delete to log allocations/deallocations, but this is more manual and less scalable than using dedicated tools.

确保动态内存管理正确的常用方法

These practices will help you avoid leaks and memory bugs in the first place:

  • Use Smart Pointers: Replace raw pointers with std::unique_ptr (for exclusive ownership) or std::shared_ptr (for shared ownership). They automatically delete the underlying object when it's no longer needed, eliminating manual delete calls.
  • Follow RAII: Resource Acquisition Is Initialization—wrap every dynamic resource (memory, files, sockets) in an object whose destructor cleans up the resource. Standard containers like std::vector or std::unordered_map already do this for their internal storage.
  • Avoid Manual Memory Management: Whenever possible, use standard library containers instead of raw arrays or manually allocated objects. For example, instead of new Stack<int>, let a container manage the stack instances.
  • Enable Compiler Warnings: Turn on -Wall -Wextra (GCC/Clang) or equivalent in Visual Studio. Warnings will catch issues like uninitialized pointers, missing delete calls, and unsafe pointer usage.
  • Test Edge Cases: Make sure to test scenarios like emptying stacks, popping from specific stacks (pop_at), and exception safety (what if new throws an exception? Does your code avoid leaks?).

Issues in Your SetOfStacks Implementation

Looking at your code, there's a critical memory leak in the pop method:

void pop(void) {
    Stack<int> *current_stack = all_stacks[this->stack_index];
    if (current_stack->getSize() > 0) {
        current_stack->pop();
    }
    if (current_stack->getSize() == 0) {
        all_stacks.erase(this->stack_index); // Erases the entry from the map
        --this->stack_index;
        --this->stack_count;
        // ❌ Missing delete current_stack! The stack's memory is never freed.
    }
}

When you erase the stack from all_stacks, you don't delete the underlying Stack<int> object—this leaves that memory allocated forever, causing a leak.

Another minor issue: pop_at doesn't handle stacks that become empty after popping. While this doesn't cause a leak (the stack will be deleted in the destructor), it leaves empty stacks in your map unnecessarily, wasting a small amount of memory.

Fix Suggestion: Use Smart Pointers

Replace your std::unordered_map<int, Stack<int> *> with std::vector<std::unique_ptr<Stack<int>>>. This way, when you remove an element from the vector, the unique_ptr automatically deletes the stack for you:

class SetOfStacks {
private:
    std::vector<std::unique_ptr<Stack<int>>> all_stacks;
    int max_capacity;
public:
    void push(int plate_number) {
        if (!all_stacks.empty() && all_stacks.back()->getSize() < max_capacity) {
            all_stacks.back()->push(plate_number);
            return;
        }
        all_stacks.emplace_back(std::make_unique<Stack<int>>());
        all_stacks.back()->push(plate_number);
    }

    void pop(void) {
        if (all_stacks.empty()) return;
        all_stacks.back()->pop();
        if (all_stacks.back()->getSize() == 0) {
            all_stacks.pop_back(); // Automatically deletes the empty stack
        }
    }

    int peek(void) {
        return all_stacks.back()->peek();
    }

    void pop_at(int stack_id) {
        if (stack_id >= 0 && stack_id < static_cast<int>(all_stacks.size())) {
            all_stacks[stack_id]->pop();
            // Optional: Remove empty stack if needed
            if (all_stacks[stack_id]->getSize() == 0) {
                all_stacks.erase(all_stacks.begin() + stack_id);
            }
        } else {
            std::cout << "栈ID范围为0到" << (all_stacks.size() - 1) << "\n";
        }
    }

    int how_many_stacks(void) {
        return static_cast<int>(all_stacks.size());
    }

    int stack_occupancy(void) {
        return all_stacks.back()->getSize();
    }

    int which_stack(void) {
        return static_cast<int>(all_stacks.size()) - 1;
    }

    SetOfStacks(int capacity) : max_capacity(capacity) {
        all_stacks.emplace_back(std::make_unique<Stack<int>>());
    }

    ~SetOfStacks() {
        // No need for manual deletion—vector and unique_ptr handle it!
    }
};

This eliminates the need for manual delete calls entirely, making memory leaks impossible in this class.

内容的提问来源于stack exchange,提问作者ptorr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 17:47:49