Исключения при попытке сдвинуть указатель C++

Я пишу класс для выделения памяти (динамической) и сохранением количества байтов который занимает блок памяти (И еще количество указателей на блок памяти, но это нужно для другого класса). Работает примерно так: Выделяем память под необходимое количество элементов и плюсуем к этому количеству 16 байтов (для размера и указателей). После сдвигаем полученный указатель на 16 байтов. Используем. Если нужен размер - сдвигаем назад на 16 байтов, получаем размер и опять сдвигаем указатель на 16 байтов вперёд. Аналогично с указателями, но 8 байтами. Для этого у меня есть отдельные функции.

Да только проблема: Почему-то они никак не хотят сдвигать 16 байтов. Сдвигают на 10 байтов и всё. После выдаёт исключение, программа завершается. (Проверил в отладчике, visual studio 2022) Куда деваются 6 байтов - не знаю. Код ниже. (Не надо только говорить, мол, почему я там malloc юзаю. Знаю я, что это устаревшая функция и что есть new/delete. Потом переделаю)

#include <iostream>
#include <vector>
#include <malloc.h>

using namespace std;

typedef void* voidptr;
typedef bool* byteptr;

#ifdef _WIN64
    #define BSMARTHEAP_SIZEINFOBLOCK 16
    #define SIZET_BYTES 8
#else
    #define BSMARTHEAP_SIZEINFOBLOCK 8
    #define SIZET_BYTES 4
#endif

template<class T>
T* move_pointer_right(voidptr ptr, size_t bytes)
{
    byteptr pointer = (byteptr)ptr;
    pointer += bytes;
    return (T*)pointer;
}

template<class T>
T* move_pointer_left(voidptr ptr, size_t bytes)
{
    byteptr pointer = (byteptr)ptr;
    pointer -= bytes;
    return (T*)pointer;
}

class Bsmartheap
{
private:
    vector<voidptr>infoheap;
public:

    // size(8bytes) links(8bytes) data

    voidptr allocate_memory(size_t SizeBytes);
    void free_memory(voidptr _Block);
    voidptr reallocate_block(voidptr _Block, size_t NewSize);
    size_t size_block(voidptr _Block);
    size_t pointers_to_block(voidptr _Block);
};

size_t Bsmartheap::size_block(voidptr _Block)
{
    const size_t sizevec = infoheap.size();
    for (size_t x = 0; x < sizevec; x++)
    {
        if (&infoheap[x] == _Block)
        {
         
            return move_pointer_left<size_t>(infoheap[x], BSMARTHEAP_SIZEINFOBLOCK)[0]; // exception here
        }
    }
    return 0;
}

size_t Bsmartheap::pointers_to_block(voidptr _Block)
{
    const size_t sizevec = infoheap.size();
    for (size_t x = 0; x < sizevec; x++)
    {
        if (&infoheap[x] == _Block)
        {
            return move_pointer_left<size_t>(infoheap[x], BSMARTHEAP_SIZEINFOBLOCK)[1];
        }
    }
    return 0;
}

voidptr Bsmartheap::reallocate_block(voidptr _Block, size_t NewSize)
{
    if (NewSize == 0)
    {
        free_memory(_Block);
        return nullptr;
    }

    const size_t vecsize = infoheap.size();
    for (size_t x = 0; x < vecsize; x++)
    {
        if (&infoheap[x] == _Block)
        {
            size_t* infoblock = move_pointer_left<size_t>(infoheap[x], BSMARTHEAP_SIZEINFOBLOCK);
            size_t Countpointers = infoblock[1];
            voidptr tmpptr = realloc(move_pointer_left<void>(infoheap[x], BSMARTHEAP_SIZEINFOBLOCK), BSMARTHEAP_SIZEINFOBLOCK + NewSize);
            if (tmpptr == nullptr)
            {
                throw exception("realloc return a nullptr");
                return nullptr;
            }
            size_t* setinfoblock = (size_t*)tmpptr;
            setinfoblock[0] = NewSize;
            setinfoblock[1] = Countpointers;

            tmpptr = move_pointer_right<void>(tmpptr, BSMARTHEAP_SIZEINFOBLOCK);
            
            infoheap[x] = tmpptr;
            return &infoheap[x];
        }
    }
    return nullptr;
}

void Bsmartheap::free_memory(voidptr _Block)
{
    const size_t sizevec = infoheap.size();
    for (size_t x = 0; x < sizevec; x++)
    {
        if (&infoheap[x] == _Block)
        {
            free(move_pointer_left<void>(infoheap[x], BSMARTHEAP_SIZEINFOBLOCK));
            infoheap.erase(infoheap.begin() + x);
            return;
        }
    }
}

voidptr Bsmartheap::allocate_memory(size_t Sizebytes)
{
    if (Sizebytes == 0)
    {
        throw exception("Size is null");
        return nullptr;
    }

    voidptr _Ptr = malloc(BSMARTHEAP_SIZEINFOBLOCK + Sizebytes);

    if (_Ptr == nullptr)
    {
        throw exception("malloc return a nullptr");
        return nullptr;
    }

    size_t* infoblock = (size_t*)_Ptr;
    infoblock[0] = Sizebytes;
    infoblock[1] = 0;
    _Ptr = move_pointer_right<void>(_Ptr, BSMARTHEAP_SIZEINFOBLOCK);

    infoheap.push_back(_Ptr);
    return &infoheap[infoheap.size() - 1];
}

static Bsmartheap heap;


int main()
{
    char* ptr = (char*)heap.allocate_memory(6);
    const char* str = "Hello";
    for (size_t x = 0; x < 6; x++)
    {
        ptr[x] = str[x];
    }

    cout << ptr << endl;
    cout << heap.size_block(ptr) << endl;
    cout << heap.pointers_to_block(ptr) << endl;

    heap.free_memory(ptr);

    return 1;
}

Ответы (1 шт):

Автор решения: Harry

А зачем вы возвращаете не полученный адрес, а адрес элемента, его содержащего?

return infoheap[infoheap.size() - 1];

вместо

return &infoheap[infoheap.size() - 1];

вас спасет — но только от крэша при освобождении в памяти, потому что у вас таких обращений в коде полно... Пересмотрите их самостоятельно!

→ Ссылка