Version 2
Results first I think:
Code:
Debug:
Mine: 2.328 seconds
CRT: 1.406
Release:
Mine: 0.875
CRT: 0.031
Executing this:
Code:
int main( int argc, char* argv[] )
{
char* mem = NULL;
int i, k;
clock_t start, end;
start = clock();
for ( i = 1; i < 100001; i++ )
{
mem = (char*) Allocate( i );
Free( mem );
}
end = clock();
std::cout << "Custom Delta: " << (float) ( end - start ) / (float) CLOCKS_PER_SEC << " s\n";
start = clock();
for ( i = 1; i < 100001; i++ )
{
mem = new char[i];
delete[] mem;
}
end = clock();
std::cout << "CRT Delta: " << (float) ( end - start ) / (float) CLOCKS_PER_SEC << " s\n";
if ( _CrtDumpMemoryLeaks() )
std::cout << "\nMemory leaked. Oh joy.\n";
std::cin.get();
return 0;
}
I've taken itsme86's advice as best I could and come up with this. Every block allocated is allocated to a size of <requested> + sizeof(block) (where block is a SMemBlock*). The address of block is written into the first sizeof(block) bytes and a pointer just past that address is returned to the caller.
In SMemBlock I've got the block size and (in debug builds) the __LINE__ and __FILE__ information.
I may as well just give you the code - doesn't need as much explaining as the last one:
Memory.h
Code:
#pragma once
struct SMemoryState
{
unsigned long mTotalAllocated;
unsigned long mBlockCount;
};
#ifdef _DEBUG
#define Allocate( bytes ) CMemory::MemAlloc( bytes, __LINE__, __FILE__ )
#else
#define Allocate( bytes ) CMemory::MemAlloc( bytes, NULL, NULL )
#endif
#define Free( pointer ) CMemory::MemFree( pointer )
class CMemory
{
public:
CMemory();
~CMemory();
static void* MemAlloc( size_t bytes, long line, const char* file );
static void MemFree( void* p );
SMemoryState GetMemoryState();
private:
struct SMemBlock
{
long mLine;
const char* mFile;
size_t mSize;
};
static unsigned long mAllocated;
static unsigned long mBlocks;
};
Memory.cpp
Code:
#include "stdafx.h"
#include "Memory.h"
unsigned long CMemory::mAllocated = 0;
unsigned long CMemory::mBlocks = 0;
////////
// ctor / dtor
//
CMemory::CMemory()
{
}
CMemory::~CMemory()
{
}
////////
// MemAlloc
//
void* CMemory::MemAlloc( size_t bytes, long line, const char* file )
{
if ( bytes <= 0 )
return NULL;
SMemBlock* block = new SMemBlock;
char* data = new char[bytes + sizeof(block)];
memset( data, 0, bytes + sizeof(block) );
block->mSize = bytes;
if ( line && file )
{
block->mLine = line;
block->mFile = file;
}
mAllocated += (unsigned long) bytes;
mBlocks++;
*(unsigned long*) data = *(unsigned long*) █
return ( data + sizeof(block) );
}
////////
// MemFree
//
void CMemory::MemFree( void* p )
{
SMemBlock* block;
char* pt = (char*) p - sizeof(block);
block = (SMemBlock*) *(unsigned __int64*) pt;
//#ifdef _DEBUG
// printf( "\n[MemFree] Block size: %d\n", block->mSize );
// printf( "[MemFree] File: %s\n", block->mFile );
// printf( "[MemFree] Line: %d\n", block->mLine );
//#endif
mAllocated -= (unsigned long) block->mSize;
mBlocks--;
if ( p )
delete[] pt;
delete block;
}
SMemoryState CMemory::GetMemoryState()
{
SMemoryState state;
memset( &state, 0, sizeof(SMemoryState) );
state.mTotalAllocated = mAllocated;
state.mBlockCount = mBlocks;
return state;
}
I'm not entirely sure where I could make changes to squeeze out some more performance.