c++ - 自定义内存管理器在 Release模式下工作正常,但在 Debug模式下不行

标签 c++ visual-studio memory-management memory-leaks pool

我正在尝试实现一个简单的内存管理器来试验内存池机制并跟踪内存泄漏。我正在使用 VS2019,到目前为止,我的代码仅在发布 x86 模式下运行。将构建配置更改为调试或将目标平台设置为 x64,会导致访问冲突错误。具体来说,在 Debug模式下,计算可用池大小的以下行会引发异常“引发未处理的异常:读取访问冲突。p 为 nullptr。”

    return p->end - p->next;

我的问题是为什么 Release模式可以正常工作以及如何修复 Debug模式配置中的访问冲突?对实现的任何评论、建议或评估也表示赞赏。这是我当前的代码:
#include <iostream>
#include <string>
#include <array>


struct free_store {
    char* next;
    char* end;
};

const int POOL_SIZE {500};

// memory counters
size_t alloc_count {0};
size_t dealloc_count {0};

// containers to trace memory info
std::array<void*, POOL_SIZE> m_adrs; // addresses of the reserved memory
std::array<size_t, POOL_SIZE> m_sizes; // sizes of the reserved memory
std::array<std::string, POOL_SIZE> m_adrs_str;

// memory management functionality
using pool = free_store;
pool* create_pool(size_t);
void destroy_pool(pool*);
size_t available_pool(pool*);
void* alloc_memory(pool*, size_t);
void free_memory(void* memory);

// test class
class Student {
private:
    const size_t NUM_OF_COURSES {5};
    double* scores;

public:
    Student() {
        scores = new double[NUM_OF_COURSES];
    }
    ~Student() {
        // uncomment to prevent leaks
        // delete[] scores;
    }
};

// customizing new and delete 
pool* my_pool = create_pool(sizeof(Student) * POOL_SIZE);

void* operator new(size_t sz) {
    //void* ptr {malloc(sz)};
    void* ptr = alloc_memory(my_pool, sz);
    return ptr;
}
void operator delete(void* ptr) {
    free_memory(ptr);
    //free(ptr); // I destroy the pool in the end of program
}

void test_1() {
    int* id {new int(208748301)};
    double* pass {new double(15)};
    double* bounds = {new double[2] {0, 20}};
    Student* st1 = new Student;
    Student* st2 = new Student;
    delete pass;
    delete[] bounds;
    delete st1;
    delete st2;
}

void display_results();


int main() {

    // test allocation/deallocation
    test_1();

    // show results
    display_results();

    // release resources
    destroy_pool(my_pool);

    system("pause");

} // end main function



pool* create_pool(size_t size) {
    pool* p = (pool*)malloc(size + sizeof(pool));
    p->next = (char*)&p[1];
    p->end = p->next + size;
    return p;
}

void destroy_pool(pool* p) {
    free(p);
}

size_t available_pool(pool* p) {
    return p->end - p->next;
}

void* alloc_memory(pool* p, size_t sz) {
    std::cout << "Pool Available: " << available_pool(my_pool) << " bytes" << std::endl;
    if(available_pool(p) < sz) return nullptr;
    void* memory = (void*)p->next;
    p->next += sz;
    m_adrs.at(alloc_count) = memory;
    char buf[128];
    sprintf_s(buf, "%p", memory);
    m_adrs_str.at(alloc_count) = buf;
    m_sizes.at(alloc_count) = sz;
    alloc_count++;
    return memory;
}

void free_memory(void* memory) {
    auto it {std::find(m_adrs.begin(), m_adrs.end(), memory)};
    auto idx {std::distance(m_adrs.begin(), it)};
    m_adrs.at(idx) = nullptr;
    dealloc_count++;
}

void display_results() {
    std::cout << std::endl;
    std::cout << "Number of allocations: " << alloc_count << std::endl;
    std::cout << "Number of deallocations: " << dealloc_count << std::endl << std::endl;

    std::cout << "Sizes of the reserved memory:" << std::endl;
    for(size_t i {}; i < m_sizes.size(); i++) {
        if(m_adrs_str[i] != "") {
            std::cout << "Address: " << m_adrs_str[i] << ", Size: " << m_sizes[i] << " bytes" << std::endl;
        }
    }

    std::cout << std::endl;
    std::cout << "Addresses of leaks:" << std::endl;
    for(const auto& a : m_adrs) {
        if(a != nullptr) {
            std::cout << a << std::endl;
        }
    }
}

更新 1

我发现将运行时库选项设置为 /MD正确编译代码。因此,使用 CL 在命令提示符下编译和链接程序:
>cl /MD app.cpp

所以我想问题是这个选项如何解决内存访问问题。

最佳答案

根据Microsoft documentation on Run-Time Library options , /MD将程序链接到 MSVCRT.lib这反过来又使链接器能够解析外部引用。这显然修复了 Debug模式引发的未处理异常(内存访问冲突错误)。

我不确定是否应该将此标记为问题的答案或其他详细信息,因此如果您认为有必要,请随时进行编辑。

关于c++ - 自定义内存管理器在 Release模式下工作正常,但在 Debug模式下不行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61967403/

相关文章:

c - 如何修复此错误,无法在 C 中写入另一个文件

memory-management - KVM 中的动态内存分配

c++ - C/C++ 分配器在多线程上下文中的性能如何?

c++ - "system(...)"在 C++ 中有什么作用?

c++ - std::atomic 到底是什么?

C#/Visual Studio 调试示例

java - 如何用Java处理大数据?

C++\IronPython 集成示例代码?

C++ 文件在第一行后停止读取

git - Visual Studio 2015 默认为 P4VS,即使解决方案由 git 控制