简体   繁体   English

自定义 memory 管理器在发布模式下工作正常,但在调试模式下无法正常工作

[英]Custom memory manager works fine in release mode, but not in debug mode

I'm trying to implement a simple memory manager to experiment with memory pooling mechanism and track memory leaks.我正在尝试实现一个简单的 memory 管理器来试验 memory 池机制并跟踪 memory 泄漏。 I'm using VS2019 and so far my code only runs in release x86 mode.我正在使用 VS2019,到目前为止,我的代码仅在版本 x86 模式下运行。 Changing the build configuration to debug or setting target platform to x64, results in an access violation error.将构建配置更改为调试或将目标平台设置为 x64,会导致访问冲突错误。 Specifically, in debug mode the following line which calculates the available pool size, throws an exception "Unhandled exception thrown: read access violation. p was nullptr."具体来说,在调试模式下,计算可用池大小的以下行会引发异常“引发未处理的异常:读取访问冲突。p 为 nullptr。”

    return p->end - p->next;

My question is why release mode works fine and how to fix the access violation in debug mode configuration?我的问题是为什么发布模式可以正常工作以及如何修复调试模式配置中的访问冲突? Also any comment, suggestions or appraisal of the implementation is appreciated.对实施的任何评论、建议或评估也表示赞赏。 Here is my current code:这是我当前的代码:

#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;
        }
    }
}

Update-1更新-1

I found out setting the Runtime Library option to /MD compiles the code correctly.我发现将运行时库选项设置为/MD可以正确编译代码。 Therefore to compile and link the program in command prompt using CL:因此,使用 CL 在命令提示符下编译和链接程序:

>cl /MD app.cpp

So I guess the question is how this option fixes the memory access problem.所以我想问题是这个选项如何修复 memory 访问问题。

According to Microsoft documentation on Run-Time Library options , /MD links the program to MSVCRT.lib which in turn enables the linker to resolve external references.根据有关运行时库选项的 Microsoft 文档/MD将程序链接到MSVCRT.lib ,从而使 linker 能够解析外部引用。 This appreantly fixes unhandled exception (the memory access violation error) thrown by the debug mode.这显然修复了调试模式引发的未处理异常(memory 访问冲突错误)。

I'm not sure if I should tag this as an answer or additional details for the question, so feel free to edit if you deem necessary.我不确定是否应该将此标记为问题的答案或其他详细信息,因此如果您认为有必要,请随时进行编辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 调试模式下未处理的异常,但在发行版中工作正常 - Unhandled exception in debug mode but works fine in release 调试运行良好,但不在发布模式下 - Debug runs fine, but not in release mode 在发布模式下OpenAL Soft崩溃(调试工作正常) - OpenAL Soft crashes in release mode (debug works fine) 为什么在发布模式下不能访问 for 循环,但在调试中它工作正常 - Why isn´t the for loop accessed in release mode, but in debug it works fine CImg在调试模式下引发异常,在Release中运行良好 - CImg throws an exception in Debug mode, works fine in Release 在调试模式下访问冲突,但在发布模式下很好 - Access Violation in debug mode, but fine in release mode 释放模式工作正常,但调试模式使用八度DLL提供了未处理的异常 - Release mode works fine but debug mode gives unhandled exception- using Octave DLLs SFML 2.1程序在调试模式下运行良好,但在发布模式下崩溃 - SFML 2.1 program runs fine in debug mode, but crashes in release mode GCC在调试模式下崩溃,在发布模式下运行正常吗? - GCC crash in debug mode, runs fine in release mode? 发布模式导致在调试模式下工作的循环中无限循环 - Release mode causes infinite looping in loop that works in debug mode
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM