自定义内存池分配器中的读取访问冲突

问题描述 投票:0回答:1

因此,出于学习目的,我正在尝试实现自定义内存池分配器。当前的实现非常幼稚,但这不是重点。

[当我尝试分配8字节(工作16字节)时,我的程序在第三个8字节分配时崩溃,并显示错误Exception thrown: read access violation. this->**head** was 0xFFFFFFFFFFFFFFF7.

当我在其他项目之外单独运行代码时,它可以按预期工作。但是我猜测我可能会有一些未定义的行为,这使它靠运气孤立地工作。您在下面看到的版本是我隔离使用的代码和其他项目(崩溃的地方)。

非常感谢您提供的任何帮助。

全部代码的依据:https://gist.github.com/kALLEBALIK/8d9797399cf3bce8608834472d619f98

#include "FreeLinkedList.h"

class MemoryPool
{
    struct FreeHeader {};
    using  Node = FreeLinkedList<FreeHeader>::Node;
    FreeLinkedList<FreeHeader> free_list;

    size_t total_size;
    size_t used_size;
    size_t block_size;
    void* start_pointer;

    void increment();
    void decrement();

    void reset();

public:
    MemoryPool(const size_t total_size, const size_t block_size);
    ~MemoryPool();

    void* allocate(const size_t size, const size_t alignment = 0);
    void free(void* ptr);

    void print_memory_range(void* ptr, const size_t range) const;
    void print_memory() const;
};
// MemoryPool.cpp

#include "MemoryPool.h"
#include <iostream>
#include <iomanip>

void MemoryPool::increment() { this->used_size += this->block_size; }
void MemoryPool::decrement() { this->used_size -= this->block_size; }

MemoryPool::MemoryPool(const size_t total_size, const size_t block_size)
{
    this->total_size = total_size;
    this->block_size = block_size;
    this->start_pointer = malloc(this->total_size);

    reset();
}

MemoryPool::~MemoryPool()
{
    if (this->start_pointer != nullptr)
        free(this->start_pointer);
}

void MemoryPool::reset()
{
    const size_t block_count = this->total_size / this->block_size;
    for (unsigned int i = 0; i < block_count; ++i)
    {
        this->used_size = 0;
        const size_t mem_address = reinterpret_cast<size_t>(this->start_pointer) + i * block_size;
        free_list.release(reinterpret_cast<Node*>(mem_address));
    }
}

void* MemoryPool::allocate(const size_t size, const size_t alignment)
{
    Node* free_position = free_list.obtain();

    this->increment();

    return (void*)free_position;
}

void MemoryPool::free(void* ptr)
{
    this->decrement();

    free_list.release((Node*)ptr);
}

void MemoryPool::print_memory_range(void* ptr, const size_t range) const
{
    for (size_t k = 0; k < range; ++k)
    {
        printf("%02hhx ", *reinterpret_cast<unsigned char*>(reinterpret_cast<size_t>(ptr) + k));
    }
}

void MemoryPool::print_memory() const 
{
    for (size_t i = 0; i < total_size; i += block_size)
    {
        std::cout << "0x" << std::hex << std::noshowbase << std::setw(16) << std::setfill('0') << reinterpret_cast<size_t>(this->start_pointer) + i << ": ";
        print_memory_range(reinterpret_cast<void*>(reinterpret_cast<size_t>(this->start_pointer) + i), this->block_size);
        std::cout << std::endl;
    }
}
#pragma once

template <class T>
class FreeLinkedList
{
public:
    struct Node {
        T data;
        Node* next;
    };

    FreeLinkedList(FreeLinkedList&) = delete;
    FreeLinkedList()                = default;

    ~FreeLinkedList()
    {
        delete head;
    }

    void release(Node* new_node)
    {
        new_node->next = head;
        head = new_node;
    }

    Node* obtain()
    {
        if (head == nullptr)
            return nullptr;

        Node* last = head;
        head = head->next;
        return last;
    }
private:
    Node* head;
};

#include <iostream>
#include "MemoryPool.h"
#include <iomanip>

int main()
{

    struct b8
    {
        char a1 = 1;
        char a2 = 2;
        char a3 = 3;
        char a4 = 4;
        char a5 = 5;
        char a6 = 6;
        char a7 = 7;
        char a8 = 8;
    };

    struct b16
    {
        char a1 = 1;
        char a2 = 2;
        char a3 = 3;
        char a4 = 4;
        char a5 = 5;
        char a6 = 6;
        char a7 = 7;
        char a8 = 8;
        char a11 = 1;
        char a22 = 2;
        char a33 = 3;
        char a44 = 4;
        char a55 = 5;
        char a66 = 6;
        char a77 = 7;
        char a88 = 8;
    };

    std::cout << "b16 size: " << sizeof(b16) << std::endl; // 16
    std::cout << "b8  size: " << sizeof(b8)  << std::endl; //  8


    std::cout << "-------16-byte-------" << std::endl;
    MemoryPool* mp = new MemoryPool(128, 16);
    std::cout << "-before-" << std::endl;
    mp->print_memory();

    std::cout << "-first-" << std::endl;
    void* ptr11 = new(mp->allocate(16)) b16();
    mp->print_memory();

    std::cout << "-second-" << std::endl;
    void* ptr12 = new(mp->allocate(16)) b16();
    mp->print_memory();

    std::cout << "-third-" << std::endl;
    void* ptr13 = new(mp->allocate(16)) b16();
    mp->print_memory();

    std::cout << "-fourth-" << std::endl;
    void* ptr14 = new(mp->allocate(16)) b16();
    mp->print_memory();

    std::cout << "-fifth-" << std::endl;
    void* ptr15 = new(mp->allocate(16)) b16();
    mp->print_memory();

    std::cout << "-sixth-" << std::endl;
    void* ptr16 = new(mp->allocate(16)) b16();


    std::cout << "-------8-byte-------" << std::endl;
    MemoryPool* mp2 = new MemoryPool(64, 8);
    std::cout << "-before-" << std::endl;
    mp->print_memory();

    std::cout << "-first-" << std::endl;
    void* bptr11 = new(mp2->allocate(8)) b8();
    mp->print_memory();

    std::cout << "-second-" << std::endl;
    void* bptr12 = new(mp2->allocate(8)) b8();
    mp->print_memory();

    std::cout << "-third-" << std::endl;
    void* bptr13 = new(mp2->allocate(8)) b8(); // <----- Exception thrown: read access violation.this->**head** was 0xFFFFFFFFFFFFFFF7. occurred
    mp->print_memory(); 

    std::cout << "-fourth-" << std::endl;
    void* bptr14 = new(mp2->allocate(8)) b8();
    mp->print_memory();

    mp->free(ptr11);
    mp->free(ptr12);
    mp->free(ptr13);
    mp->free(ptr14);
    mp->free(ptr15);
    mp->free(ptr16);

    mp2->free(bptr11);
    mp2->free(bptr12);
    mp2->free(bptr13);
    mp2->free(bptr14);

    delete(mp);
    delete(mp2);
}

Visual Studio错误断点的打印:Print of visual studio breakpoint

提前感谢。

c++ memory allocation
1个回答
0
投票

head似乎没有被初始化为可以安全使用的任何东西。

Node* head = nullptr;

应该解决。

© www.soinside.com 2019 - 2024. All rights reserved.