Исключения при попытке сдвинуть указатель 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 шт):
А зачем вы возвращаете не полученный адрес, а адрес элемента, его содержащего?
return infoheap[infoheap.size() - 1];
вместо
return &infoheap[infoheap.size() - 1];
вас спасет — но только от крэша при освобождении в памяти, потому что у вас таких обращений в коде полно... Пересмотрите их самостоятельно!