if (bytes < freeBlock->size)
{
MEMBLOCK newBlock;
newBlock.size = freeBlock->size - bytes;
newBlock.used = false;
freeBlock->size = bytes;
_blockList.push_back(newBlock); // crashes!!!!
_freeMem -= bytes;
}
🔒 Locked
Problem with push_back on vector
Advertisement
Original Post
Hi, i have written a custom memory allocator, and i have a vector of memblocks for housekeeping. if i need to create a new block, i call push_back, but this crashes after creating some blocks! here is the relevant code is it because the newBlock variable is local? would be nice of anyone could help me with this problem...
Couple things:
1) post the declaration of MEMBLOCK
2) newBlock.size should = bytes, not freeBlock->size - bytes
the way you have it coded now, every time you allocates "bytes" you are setting newBlock.size equal to the new current total of unused bytes.
#2 is probably your problem.
Say you have 10 bytes.
User asks for 1 byte
you are giving them 9 bytes.
Next user asks for 1 byte
You are giving them 8 bytes.
etc etc
The second time you allocate, you are out of memory.
-me
1) post the declaration of MEMBLOCK
2) newBlock.size should = bytes, not freeBlock->size - bytes
the way you have it coded now, every time you allocates "bytes" you are setting newBlock.size equal to the new current total of unused bytes.
#2 is probably your problem.
Say you have 10 bytes.
User asks for 1 byte
you are giving them 9 bytes.
Next user asks for 1 byte
You are giving them 8 bytes.
etc etc
The second time you allocate, you are out of memory.
-me
Here is the complete code
Little explanation: The _blockList vector is separated from the actual memory block, as opposed to common implementations
Little explanation: The _blockList vector is separated from the actual memory block, as opposed to common implementations
struct MEMBLOCK{ size_t size : 31; bool used : 1;};class ALLOCATOR{ size_t _chunkSize; char* _chunk; std::vector<MEMBLOCK> _blockList; size_t _freeMem; public: ALLOCATOR(const size_t chunkSize) : _chunkSize(chunkSize) { MEMBLOCK block; block.size = chunkSize; block.used = false; _chunk = new char(chunkSize); _blockList.push_back(block); _freeMem = chunkSize; } void* allocate(const size_t bytes) { if (_chunkSize < bytes || bytes == 0) return NULL; MEMBLOCK *freeBlock = NULL; size_t addr = 0; for (std::vector<MEMBLOCK>::iterator pBlock = _blockList.begin(); pBlock != _blockList.end(); ++pBlock) { if (pBlock->size >= bytes && !pBlock->used) { freeBlock = &(*pBlock); break; } else addr += pBlock->size; } if (!freeBlock) return NULL; freeBlock->used = true; if (bytes < freeBlock->size) { MEMBLOCK newBlock; newBlock.size = freeBlock->size - bytes; newBlock.used = false; freeBlock->size = bytes; _blockList.push_back(newBlock); _freeMem -= bytes; } else { freeBlock->size = bytes; _freeMem -= bytes; } return (_chunk + addr); }}ALLOCATOR mem(1024);char* my_new_string(const char* str){ char* pDest =(char*)mem.allocate(strlen(str) + 1); strcpy(pDest, str); return pDest;}void main(){ char* s1, *s2, *s3; std::cout << (s1 = my_new_string("HelloWorld!")) << std::endl; std::cout << (s2 = my_new_string("I´m going to bed now")) << std::endl; // When the third string is created, this causes push_back to crash in my allocator function std::cout << (s3 = my_new_string("Good morning, Mrs. Meyers")) << std::endl;}
another big problem you have:
you set _chunk equal to some new'd memory which you then push back to the vector. Later when you're allocating your return an offset of _chunk to the user.
That makes no sense. You're almost guaranteed to return invalid memory. because sucessive elements in the vector have absolutely no predictable locational relationship with the address stored in _chunk.
Essentially let's say you allocate _chunk at 0x00000000. Later you'll push stuff to the back of the vector, that stuff get's copied into the vector's array deal. The address of the memory in the vector's contiguous memory block is unrelated to the location of the address stored in _chunk because the data in chunk was itself copied into the vector.
if you want to be returning offsets, you want to return offsets from the front of the vector..... however that's also bad because every time a vector grows beyond it's current bounds, it copies all of itself somewhere else in memory which would then invalidate any memory addresses you've previously given out to anyone.
Basically, your architecture just won't work (unless i've just missed some important details).
The typical architecture of a memory manager uses handles so that the memory you give out can be manipulated at will by the manager without invalidating memory that other people are holding.
-me
you set _chunk equal to some new'd memory which you then push back to the vector. Later when you're allocating your return an offset of _chunk to the user.
That makes no sense. You're almost guaranteed to return invalid memory. because sucessive elements in the vector have absolutely no predictable locational relationship with the address stored in _chunk.
Essentially let's say you allocate _chunk at 0x00000000. Later you'll push stuff to the back of the vector, that stuff get's copied into the vector's array deal. The address of the memory in the vector's contiguous memory block is unrelated to the location of the address stored in _chunk because the data in chunk was itself copied into the vector.
if you want to be returning offsets, you want to return offsets from the front of the vector..... however that's also bad because every time a vector grows beyond it's current bounds, it copies all of itself somewhere else in memory which would then invalidate any memory addresses you've previously given out to anyone.
Basically, your architecture just won't work (unless i've just missed some important details).
The typical architecture of a memory manager uses handles so that the memory you give out can be manipulated at will by the manager without invalidating memory that other people are holding.
-me
Couple good links you might want to check out:
Overview:
http://www.gamasutra.com/features/20020802/hixon_01.htm
Details:
http://www.memorymanagement.org/
-me
Overview:
http://www.gamasutra.com/features/20020802/hixon_01.htm
Details:
http://www.memorymanagement.org/
-me
@Palidine
Thanks for your help. But i think my code is a little bit confusing due to the fact, that the variable named "freeBlock" is somewhat misleading.
freeBlock is the "first fit" block that is greater than or equal to the bytes the user aquired, and freeblock is then marked as used, so it is no longer a freeblock but actual the block that is related to the allocated memory.
And then, newBlock is created to store information of the remaining free bytes
Lets say, i have a single free block of 100 byte,
and the user aks me for 80 bytes,
then i set this block´s size to 80 bytes, and create a new (free block) with 20 bytes in size.
Thanks for your help. But i think my code is a little bit confusing due to the fact, that the variable named "freeBlock" is somewhat misleading.
freeBlock is the "first fit" block that is greater than or equal to the bytes the user aquired, and freeblock is then marked as used, so it is no longer a freeblock but actual the block that is related to the allocated memory.
And then, newBlock is created to store information of the remaining free bytes
Lets say, i have a single free block of 100 byte,
and the user aks me for 80 bytes,
then i set this block´s size to 80 bytes, and create a new (free block) with 20 bytes in size.
no. you're storing that offset in the array thusly:
10 total bytes
allocate 1 byte
push_back a struct with a .size = 9
allocate 1 byte
push_back a struct with a .size = 8
allocate another byte
iterate the list
addr += 9
addr += 8
return _chunk + 17;
note that the addr offset is horribly wrong
note that _chunk + 17 is no where in your vector of memory because the pointer stored in _chunk has no relationship with the memory space of the vector
-me
10 total bytes
allocate 1 byte
push_back a struct with a .size = 9
allocate 1 byte
push_back a struct with a .size = 8
allocate another byte
iterate the list
addr += 9
addr += 8
return _chunk + 17;
note that the addr offset is horribly wrong
note that _chunk + 17 is no where in your vector of memory because the pointer stored in _chunk has no relationship with the memory space of the vector
-me
Quote:
Original post by Palidine
no. you're storing that offset in the array thusly:
10 total bytes
allocate 1 byte
push_back a struct with a .size = 9
allocate 1 byte
push_back a struct with a .size = 8
allocate another byte
iterate the list
addr += 9
addr += 8
return _chunk + 17;
note that the addr offset is horribly wrong
note that _chunk + 17 is no where in your vector of memory because the pointer stored in _chunk has no relationship with the memory space of the vector
-me
I´m just using the vector for holding information about the size of the block, they have no relationship to the memory addressed by _chunk, neither physically nor logically :)
the vector only keeps track of the number of blocks and the block sizes / as well as the status (used/unused)
The problem is fixed now, it was the error detected by Enigma. Now it works :)
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement