Unable to delete pointer on heap memory - c++

I am making my own dynamic allocator in C++. But I ran into a problem where I can't free my memory.
This is the code for Test.cpp:
#include "Memory/MemoryManager.h"
int main(){
initMemory(1);
int* p = allocate<int>();
int* q = allocate<int>();
int* r = allocate<int>();
cout<<p<<endl;
cout<<q<<endl;
cout<<r<<endl;
freeAddress<int>(q);
return 0;
}
MemoryManager.h:
#ifndef MEMORY_MANAGER_INCLUDED
#define MEMORY_MANAGER_INCLUDED
#include <iostream>
#include <map>
#include <memory>
using namespace std;
char* memory;
char* current;
map<void*, size_t> freePointers;
void initMemory(size_t size){
memory = (char*)malloc(size);
current = memory;
}
template<typename T> T* allocate(){
T* address = NULL;
for (auto p : freePointers){
if (p.second == sizeof(T)){
address = static_cast<T*>(p.first);
}
}
if (address == NULL){
address = new(current) T();
current += sizeof(T);
}
return address;
}
template<typename T> T* allocate(size_t size){
T* address = NULL;
for (auto p : freePointers){
if (p.second == sizeof(T) * size){
return static_cast<T*>(p.first);
}
}
if (address == NULL){
address = new(current) T[size];
current += sizeof(T) * size;
}
return address;
}
template<typename T> void freeAddress(T* address){
freePointers.insert({(void*)address, sizeof(*address)});
delete address;
}
template<typename T> void freeAddress(T* address, size_t size){
freePointers.insert({(void*)address, sizeof(*address) * size});
delete [] address;
}
#endif
Output:
0x55ee37729e70
0x55ee37729e74
0x55ee37729e78
0x55ee37729e70
0x55ee37729e78
free(): invalid pointer
I know that I can't delete pointers on stack memory but I am not using it at all. Also please point out if I am doing something wrong or performance expensize. Please help.

You allocate a large chunk of memory with malloc, then call delete on some pointer into the allocated memory.
In your code, q is (memory + sizeof(int)). This pointer has never been returned by an allocation and therefore cannot be freed. This is the reason for the error.
Moreover, mismatching malloc with delete is undefined behavior. You should instead call free() on the original memory pointer as cleanup in the end, and never call delete on individual values.
If you want to call the destructor in freeAddress, use address->~T();.

You are allocating a single 1-byte block of memory one time, in your initMemory(). You are using malloc() for that allocation, so that memory block must be freed with free() when you are done using it, but you are not doing that.
Your freeAddress() is delete'ing memory that was never allocated with new. Inside of allocate(), you are using placement-new instead of new, they are not the same thing. When you use placement-new, you have to call an object's destructor manually, not free() or delete it.
And you certainly do not want to free memory that you are going to reuse later. That defeats the whole purpose of caching "freed" memory.
And new[] uses more memory than you request, so that it can store info for delete[] to know know how many elements to free, and how to free them. You won't know how much extra overhead that is, as it is implementation defined. So it is not safe to use new[] in this situation.
Try something more like this instead
#include "Memory/MemoryManager.h"
int main(){
initMemory(sizeof(int) * 3);
int* p = allocate<int>();
int* q = allocate<int>();
int* r = allocate<int>();
cout << p << endl;
cout << q << endl;
cout << r << endl;
freeAddress<int>(q);
doneMemory();
return 0;
}
#ifndef MEMORY_MANAGER_INCLUDED
#define MEMORY_MANAGER_INCLUDED
#include <iostream>
#include <map>
#include <memory>
char* memory;
char* current;
size_t available;
std::map<void*, size_t> freePointers;
void initMemory(size_t size){
memory = (char*) malloc(size);
current = memory;
available = (memory) ? size : 0;
}
void doneMemory(){
freePointers.clear();
free(memory);
memory = current = nullptr;
available = 0;
}
template<typename T>
T* allocate(){
T *address = nullptr;
for (auto iter = freePointers.begin(); iter != freePointers.end(); ++iter){
if (iter->second == sizeof(T)){
address = static_cast<T*>(iter->first);
freePointers.erase(iter);
break;
}
}
if (!address){
if (available < sizeof(T)){
return nullptr;
}
address = static_cast<T*>(current);
current += sizeof(T);
available -= sizeof(T);
}
return new(address) T();
}
template<typename T>
T* allocate(size_t count){
T *address = nullptr;
size_t size = count * sizeof(T);
for (auto iter = freePointers.begin(); iter != freePointers.end(); ++iter){
if (iter->second == size){
address = static_cast<T*>(iter->first);
freePointers.erase(iter);
break;
}
}
if (!address){
if (available < size){
return nullptr;
}
address = static_cast<T*>(current);
current += size;
available -= size;
}
for(size_t i = 0; i < count; ++i)
new(address+i) T();
}
return address;
}
template<typename T>
void freeAddress(T* address){
address->~T();
freePointers.insert({(void*)address, sizeof(T)});
}
template<typename T>
void freeAddress(T* address, size_t count){
for (size_t i = 0; i < count; ++i)
address[i].~T();
freePointers.insert({(void*)address, sizeof(T) * count});
}
#endif
That being said, this isn't a very safe or robust memory allocator, but it should get you started.
If you really want to create a custom memory allocator, you should write a class that follows the Allocator strategy, and then you can use that allocator with standard C++ containers, like std::vector. Let the compiler and standard library handle most of the hard work for you.

Related

How to correctly delete an allocated array (queue data structure)

I created a queue data structure using a struct and a dynamically allocated array, I don't understand what is the right way to free or delete it without any memory leaks.
I have tried using the following:
delete[] q->data;
delete[] &(q->data);
delete &(q->data);
#include "queue.h"
void initQueue(queue* q, unsigned int size)
{
q->maxSize = size;
q->size = 0;
q->data = new unsigned int[size];
q->front = 0;
q->rear = 0;
}
void enqueue(queue* q, unsigned int newValue)
{
if (q->size != q->maxSize)
{
q->data[q->rear] = newValue;
q->size++;
q->rear++;
}
else
{
std::cout << "Queue is full! you can clean it and initialize a new one" << std::endl;
}
}
int dequeue(queue* q)
{
int i = 0;
if (q->size == 0)
{
std::cout << "Queue is empty!" << std::endl;
return EMPTY;
}
else
{
q->front++;
q->size--;
return q->data[q->front];
}
}
void cleanQueue(queue* q)
{
//the delete function
}
The technical right answer here is to delete q->data, as others have suggested. But...
right way to free or delete it without any memory leaks
The right way in C++, unless you're doing some exotic with allocation, is not to do your own memory management. Write a class that allocates in the constructor, and deletes in the destructor, as Chris suggested, is a great way to learn about RAII and how it saves you from the mental burden of manually writing "delete" everywhere.
But the right right way, if someone was paying me? I'd skip all that and use a vector.
#include <vector>
class MyQueue {
public:
MyQueue(unsigned int size) : data(size) { }
void enqueue(unsigned int value) { /* whatever... */ }
int dequeue() { /* whatever... */ }
private:
std::vector<unsigned int> data;
};
When this class goes out of scope or gets deleted, the vector will automatically be cleaned up. You don't even need to free or delete anything.

Segfault with std::vector =-operation to uninitialized space

I get segmentation faults when I use the =-operator to copy a struct that contains a std::vector to uninitialized memory.
The critical code looks like that:
template<typename T>
ComponentContainer
{
T* buffer;
size_t capacity;
size_t m_size;
public:
ComponentContainer();
~ComponentContainer();
size_t size();
void resize(size_t size);
T & operator[](size_t index);
};
template<typename T>
void ComponentContainer<T>::resize(size_t newSize)
{
if(this->m_size >= newSize)
{
this->m_size = newSize;
}
else
{
if(this->capacity < newSize)
{
const size_t newCapacity = capacity*2;
T* newBuffer = (T*)malloc(newCapacity*sizeof(T));
for(size_t i = 0; i<m_size; i++)
{
// checks if this->buffer[i] is valid intialized memory
if(pseudo_checkIfElementIsInitialized(i))
{
// when this is uncommented no segfault happens
//new (&newBuffer[i]) T();
newBuffer[i] = this->buffer[i]; // <- segfault happens here
}
}
this->capacity = newCapacity;
free(this->buffer);
this->buffer = newBuffer;
}
this->m_size = newSize;
}
}
The T-type is a struct with a std::vector of structs when I get the segfault.
I suspect that the std::vector =-operator uses somehow the left side variable newBuffer[i] and the segmentation fault happens since newBuffer[i] is not initialized.
Objects will be created only with in-placement new with the function T & operator[](size_t index). The malloc should only allocate the memory without initializing anything.
I tried to write a simple example but that hasn't worked out so well:
#include <iostream>
#include <vector>
struct Hello
{
Hello()
{
std::cout << "constructor" << std::endl;
}
~Hello()
{
std::cout << "destructor" << std::endl;
}
std::vector<double> v = std::vector<double>(1);
};
int main()
{
Hello* buffer = (Hello*)malloc(1*sizeof(Hello));
char* noise = (char*)buffer;
for(size_t i = 0; i<sizeof(Hello); i++)
{
noise[i] = 100;
}
auto tmp = Hello();
tmp.v[0] = 6.6;
//new (&buffer[0]) Hello();
buffer[0] = tmp;
std::cout << buffer[0].v[0] << std::endl;
return 0;
}
It works fine without segfault. I assume that is because the uninitialized memory was just by chance ok for the std::vector =-operation.
So
a) is that theory correct
and if yes
b) how to solve this problem without using a default constructor (T()) for every class that i use as T for my ComponentContainer
Well, yeah. You can't assign to an object that doesn't exist.
Uncomment the line that fixes it!
If you can't default construct, then copy construct:
new (&newBuffer[i]) T(this->buffer[i]);
And if you can't do that, then, well, you know the rest.
The malloc should only allocate the memory without initializing anything.
Is it possible that you've underestimated the weight of this statement? You don't just get memory then decide whether or not to initialise it with some values. You have to actually create objects before using them; this is not optional. You're programming C++, not manipulating bits and bytes on a tape :)

Issue accessing free list nodes by memory address in pool allocator

I'm attempting to write a simple pool allocator for allocation and deallocation in c++ as part of a uni course task. We were given a reference to to git-user floooh's oryol engine, https://github.com/floooh/oryol/blob/master/code/Modules/Core/Memory/poolAllocator.h, hence I try to do something similar by splitting the pool into puddles that are allocated when needed. Starting with one and then incrementing as memory demands increase.
Each puddle in my case maintains its own free list of nodes and I fail already in creating the first puddle: I get segmentation fault when I try to access node struct data members. Below is my pool allocator class description along with constructor and function for adding a puddle. I commented in caps lock "SEGMENTATION FAULT" in allocNewPuddle() where it fails, line 10 in that function.
Class description:
template<class T> class memAllocator {
public:
memAllocator();
~memAllocator();
struct Puddle;
struct mNode {
mNode* nextN;
mNode* prevN;
uint puddle;
};
struct Puddle {
mNode* headN_free;
mNode* headN_occ;
};
uint numPuddles;
static const uint nodesInPuddle = 512;
static const uint maxPuddles = 512;
Puddle* puddles[maxPuddles];
uint nodeSize;
uint elemSize;
uint puddleStructSize;
void allocNewPuddle();
void* allocate();
void deallocate(void* obj);
void* findNextFreeNode();
template<typename... ARGS> T* create(ARGS&&... args);
void destroy(T* obj);
};
Constructor:
template<class T>
memAllocator<T>::memAllocator() // creates instance of allocator starting with one puddle allocated
{
this->numPuddles = 0;
this->nodeSize = sizeof(mNode);
this->elemSize = nodeSize + sizeof(T);
this->puddleStructSize = sizeof(Puddle);
allocNewPuddle();
}
Add a new puddle:
template<class T>
void memAllocator<T>::allocNewPuddle() // allocates a new puddle
{
// allocate memory for one puddle
assert(numPuddles < maxPuddles);
Puddle* newPuddle = (Puddle*) malloc(puddleStructSize + nodesInPuddle * elemSize);
// allocate nodes in free list pointed to by puddle struct
newPuddle->headN_free = (mNode*) (newPuddle + puddleStructSize + (nodesInPuddle-1)*elemSize);
for (int i = nodesInPuddle-2; i >= 0; i--) {
mNode* curNode = (mNode*) (newPuddle + puddleStructSize + i*elemSize);
// Fails here when attempting to access mNode struct members
curNode->puddle = numPuddles; // SEGMENTATION FAULT HERE ON FIRST ITERATION
curNode->prevN = nullptr;
curNode->nextN = newPuddle->headN_free;
curNode->nextN->prevN = curNode;
newPuddle->headN_free = curNode;
}
newPuddle->headN_occ = nullptr;
puddles[numPuddles] = newPuddle;
numPuddles++;
}
Here is my main.cc:
#include "memAllocator.h"
#include <iostream>
class Test {
public:
Test();
~Test();
int arr[5];
};
Test::Test() {
for (int i = 0; i < 5; i++) {
this->arr[i] = i;
}
}
Test::~Test() {
std::cout << "destructor called" << std::endl;
}
int main(int argc, char* argv[]) {
memAllocator<Test> memPool = memAllocator<Test> ();
Test* test = memPool.create();
for (int i = 0; i < 5; i++) {
std::cout << test->arr[i] << std::endl;
}
memPool.destroy(test);
for (int i = 0; i < 5; i++) {
std::cout << test->arr[i] << std::endl;
}
}
My guess is that I am doing something horribly naïve with c++ pointers, but from what I know the above should work. If not then I look forward to a good scolding.
Oh, and as you can see I'm not bothering to align memory since it is a small assignment, and as I understand this is not essential for it to work it only makes it faster, but is it possible this can cause wrong memory to be read and written to as more is demanded?
You have incorrect address calculation in line
mNode* curNode = (mNode*) (newPuddle + puddleStructSize + i*elemSize);
newPuddle is Puddle pointer, but you trying to add bytes. Thus you have new address far beyond end of allocated memory buffer. So you must add explicit cast to byte pointer (char, uint8_t etc)
mNode* curNode = (mNode*) ((char*)newPuddle + puddleStructSize + i*elemSize);
You must fix this line too
newPuddle->headN_free = (mNode*) (newPuddle + puddleStructSize + (nodesInPuddle-1)*elemSize);

Deleting Pointer Causing Debug Assert

I've been working on a memory pool allocator class, and no major problems have arisen, sans Visual Studio's debug assertion (_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)) being thrown whenever I try to free the memory allocated by new with delete.
typedef uintptr_t uptr;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
struct FreeList
{
FreeList *next;
};
template<class T, u8 alignment, u32 poolSize>
class PoolAllocator
{
private:
u8 _paddedSize; // The size in bytes of each allocated chunk of memory.
u32 _numAllocations;// The number of allocations made by the pool.
u32 _freeBytes; // The number of bytes left in the pool.
u32 _usedBytes; // The number of bytes currently occupied in the pool.
FreeList* _freeListHead; // A pointer to a freed space in memory.
public:
PoolAllocator() :
_paddedSize((sizeof(T) > sizeof(uptr) ? sizeof(T) : sizeof(uptr))),
_numAllocations(0),
_freeBytes(0),
_usedBytes(0),
_freeListHead(nullptr)
{
_freeListHead = reinterpret_cast<FreeList*>(operator new (_paddedSize * poolSize));
_freeBytes = _paddedSize * poolSize;
uptr current = reinterpret_cast<uptr>(_freeListHead);
uptr last = current + (_paddedSize * poolSize);
for (int i = 0; i < poolSize-1; i++)
{
uptr next = current + _paddedSize;
(reinterpret_cast<FreeList*>(current))->next = reinterpret_cast<FreeList*>(next);
current += _paddedSize;
}
reinterpret_cast<FreeList*>(current)->next = nullptr;
}
T *allocate()
{
if (_freeListHead != nullptr && _freeBytes >= _paddedSize) // Make sure the pool has memory left
{
uptr *toReturn = reinterpret_cast<uptr*>(_freeListHead); // Cast the pointer to a modifiable data type.
_freeListHead = _freeListHead->next; // VITAL THAT THIS IS BEFORE SETTING DATA TO 0.
*toReturn = 0; // Set the data at the memory location to 0.
_freeBytes -= _paddedSize;
_usedBytes += _paddedSize;
_numAllocations++;
printf("Allocated %d bytes of memory at %p.\n", _paddedSize, toReturn);
return reinterpret_cast<T*>(toReturn);
}
else
{
printf("Pool allocator out of memory! Returning nullptr.\n");
return nullptr;
}
}
void free(T **ptr)
{
FreeList *newHead = reinterpret_cast<FreeList*>(*ptr);
*ptr = nullptr;
newHead->next = _freeListHead;
_freeListHead = newHead;
_freeBytes += _paddedSize;
_usedBytes -= _paddedSize;
_numAllocations--;
printf("Freed %d bytes of memory at %p.\n", _paddedSize, _freeListHead);
}
void clear()
{
assert(_usedBytes == 0);
FreeList *head = _freeListHead;
while (head != 0)
{
FreeList *next = head->next;
delete reinterpret_cast<T*>(head);
head = next;
}
_paddedSize = 0;
_numAllocations = 0;
_freeBytes = 0;
_usedBytes = 0;
_freeListHead = nullptr;
}
};
The test code I am using:
int main()
{
PoolAllocator<int, 4, 4> pool;
int *a, *b, *c, *d, *e;
a = pool.allocate();
b = pool.allocate();
c = pool.allocate();
d = pool.allocate();
pool.free(&a);
e = pool.allocate();
printf("A | %p\t%d\nB | %p\t%d\nC | %p\t%d\nD | %p\t%d\nE | %p\t%d\n", a, 0, b, *b, c, *c, d, *d, e, *e);
pool.free(&b);
pool.free(&c);
pool.free(&d);
pool.free(&e);
pool.clear();
return 0;
}
The problem area lies here:
void clear()
{
assert(_usedBytes == 0);
FreeList *head = _freeListHead;
while (head != 0)
{
FreeList *next = head->next;
delete reinterpret_cast<T*>(head); // Debug assert
head = next;
}
_paddedSize = 0;
_numAllocations = 0;
_freeBytes = 0;
_usedBytes = 0;
_freeListHead = nullptr;
}
What this code is supposed to do is increment through the linked list of memory locations where individual pieces of data of type T are being stored. My reasoning for this being a valid piece of code is that, because the initially allocated memory is divided into pieces the size of sizeof(T). Therefor, I assumed that it would be appropriate to typecast the memory address to a pointer of type T* so that the individual block of memory would be completely deallocated. This would be done for the entire linked list, ensuring that all allocated memory is freed. However, when I run the code, it always throws the assert on the delete.
Stepping through the code showed that after the first iteration of typecasting and deleteing, the pointers take on strange values (the next variable, for instance:
next 0x004b2864 {next=0xfeeefeee {next=??? } } FreeList *
Whereas before, it was
next 0x006c2864 {next=0x006c2860 {next=0x006c285c {next=0x00000000
} } } FreeList *
just as it should be). I have tried this approach many different times in many different ways, including typecasting to void* instead of T*.
This problem has had me stumped for days, and any help would be appreciated. Thank you.
reinterpret_cast<T*>(head)->~T();
I tested this and not getting the assert anymore by replacing delete reinterpret_cast(head);
You can't call delete on head because the memory wasn't allocated by calling new T();
This will not compile:
struct FreeList
{
FreeList *next;
};
... but the following will:
struct FreeList
{
struct FreeList *next;
};
Otherwise, an error about incomplete struct definition or unknown type FreeList will be raised by the compiler.

Memory leaks passing dynamic variables recursively

I have a recursive function that requires me to create a new array every time the function is called. The function also requires the array that was previously created:
void myFunc(int* prevArray)
{
int newSize;
//do some calculations to find newSize
int* newArray;
newArray = new int[newSize];
//do some calculations to fill newArray
//check some stopping condition
myFunc(newArray);
}
This function leaks memory, but I can't avoid that by adding
delete[] newArray;
since I can only add that after calling the function again. How can I solve this?
You can solve this by making use of dynamic memory allocation.
// allocate initial size
const int INITIAL_SIZE = 5;
int *myArray = malloc(sizeof(int) * INITIAL_SIZE));
int myFunc(int *aArray, int numAllocated) {
int numElements = calculateNewSize();
if (numElements != numAllocated) {
// allocate new size
realloc(aArray, (numElements * sizeof(int));
}
return numElements;
}
Now you can call myFunc like this:
int numElements;
numElements = myFunc(myArray, numElements);
When your done using myFunc don't forget to free the memory
free(myArray);
Try something like
void myFunc(int* prevArray)
{
int newSize;
...newArray = new int[newSize];
myFunc(newArray);
delete[] newArray;
}
or better yet use std::unique_ptr to control the newArray memory. In this way you will follow the rule of thumb regarding dynamic memory - that it should have one owner, responsible for both allocating and freeing it.
You might just use a vector and swap the new result into the final result.
#include <iostream>
#include <vector>
struct X { ~X() { std::cout << "Destruction\n"; } };
void recursive(unsigned n, std::vector<X>& result) {
// Put new_result in a scope for destruction
{
std::vector<X> new_result(1);
// Do something
// The previous result is no longer needed
std::swap(result, new_result);
}
// Next recursion
if(n) {
std::cout << "Call\n";
recursive(--n, result);
}
}
int main() {
std::vector<X> result(1);
std::cout << "Call\n";
recursive(3, result);
return 0;
}