Кастомный аллокатор

68
20 марта 2022, 01:40

Есть такой аллокатор:

template<class T>
class Allocator
{   
public:
    using value_type = T;
    Allocator() noexcept {}
    template<class _Other>
    Allocator(const Allocator<_Other>&) noexcept
    {   
        //std::cout << typeid(_Other).name() << std::endl;
    }
    void deallocate(T* const ptr, const size_t count)
    {   
        std::cout << "Allocator::deallocate " << ptr << std::endl;
        std::free(ptr);
    }
    T* allocate(const size_t count)
    {   
       if(count > std::numeric_limits<size_t>::max() / sizeof(T) )
            throw std::bad_alloc();
        void* ptr = std::malloc(count);
        std::cout << "Allocator::allocate " << ptr << std::endl;
        return static_cast<T*>(ptr);
    }
};
class A
{
public:
    A()
    {
        std::cout << "A() " << this << std::endl;
    }
    ~A()
    {
        std::cout << "~A() " << this  << std::endl;
    }
};

И так я его использую:

int main(int argc, char* argv[])
{
    std::vector<A, Allocator<A>> vec;
    vec.push_back(A());
    return 0;
}

Вот что выводит программа:

Allocator::allocate 00ED7A48
A() 00DCFA33
Allocator::allocate 00ED7DA0
~A() 00DCFA33
~A() 00ED7DA0
Allocator::deallocate 00ED7DA0
Allocator::deallocate 00ED7A48

Почему вызывается конструктор A()? Судя по cppreference std::malloc не вызывает конструктор.

Не совсем понимаю почему программа падает с сообщением

HEAP_CORRUPTION DETECTED: after Normal block(#152) at 0x00ED7A48 CRT detected that the application wrote to memory after end of heap buffer;

при попытке удалить второй объект?

Answer 1

Почему вызывается конструктор A()

Потому что вы создаете обьект этого типа, чтобы добавить в конец вектора.

почему программа падает с сообщением

При вызове std::vector::push_back вектор просит своему распределителью выделять память для одного элемента(на самом деле резервируется память с запасом_ буфер элементов, чтобы каждый раз не выполнить выделение). Для этого вызывается Allocator::allocate с аргументом 1(один элемент). У вас же эта функция выделит память на один байт, поскольку вы вызываете malloc(1), а нужно как минимум sizeof(T) байт.

И технически ваш распределитель пока еще не подходит для использования в векторе, поскольку отсутствуют много необходимых определений (в частности Allocator::rebind, Allocator::reallocate, псевдонимы всех нужных типов и т.д.) , плюс, если malloc не найдет достаточной памяти, то никогда не будет генерироваться исключение, поскольку std::numeric_limits<size_t>::max() / sizeof(T) вполне может быть, например, восемьнадцизначным число (сами посчитайте сколько гиг). Так что эту ошибку тоже нужно исправлять.

А вообше я бы использовал new и delete потому что разница времени выполнения неощутимая, и new вызывает new_hendler, когда не может найти память, и теперь функция new_hendler пытается найти память используя другую стратегию. А malloc этого не делает...

READ ALSO
Помогите с лямбда выражением для сортировки

Помогите с лямбда выражением для сортировки

Проблема с лямбда функцией, вроде написал сортировку вектора по остаткам по возрастанию, так, чтобы числа с одинаковыми остатками выводились...

104
(Считывание/Запись) работа с файлами С++

(Считывание/Запись) работа с файлами С++

У меня есть файл с 40 вопросамиМоя задача, поместить все 40 вопросов в вектрок, после чего, выводить от туда один рандомный вопрос

74
Вызов функции_члена шаблонного базового класса из функции производного шаблонного класса

Вызов функции_члена шаблонного базового класса из функции производного шаблонного класса

Знаю, что нужно вызвать f() первыйм или вторым вариантомНо почему является ошибкой просто вызов f(); ? Ведь и так ясно, что вызывается для данного...

70
Память под контейнеры выделяется в стеки или куче?

Память под контейнеры выделяется в стеки или куче?

как выделяется память под контейнеры vector, map в с++

95