etk/etk-core/Allocator.cpp

792 lines
26 KiB
C++

/** @file
* @author Edouard DUPIN
* @copyright 2017, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#include <etk/Allocator.hpp>
#include <stdlib.h>
void* operator new (size_t size) {
return malloc(size);
}
void* operator new[] (size_t size) {
return malloc(size);
}
void operator delete (void* ptr) {
free(ptr);
}
void operator delete[] (void* ptr) {
free(ptr);
}
#if ETK_MEMORY_CHECKER > 0
#include <pthread.h>
#define ETK_MEM_DEBUG_LEVEL 4
#define ETK_MEMORY_PRINT(...) \
do { \
printf("[PRINT] "); \
printf(__VA_ARGS__); \
printf("\n"); \
} while (false)
#if ETK_MEM_DEBUG_LEVEL > 0
#define ETK_MEMORY_ERROR(...) \
do { \
printf("[ERROR] "); \
printf(__VA_ARGS__); \
printf("\n"); \
} while (false)
#else
#define ETK_MEMORY_ERROR(...) do {} while (false)
#endif
#if ETK_MEM_DEBUG_LEVEL > 1
#define ETK_MEMORY_WARNING(...) \
do { \
printf("[WARNING] "); \
printf(__VA_ARGS__); \
printf("\n"); \
} while (false)
#else
#define ETK_MEMORY_WARNING(...) do {} while (false)
#endif
#if ETK_MEM_DEBUG_LEVEL > 2
#define ETK_MEMORY_INFO(...) \
do { \
printf("[INFO] "); \
printf(__VA_ARGS__); \
printf("\n"); \
} while (false)
#else
#define ETK_MEMORY_INFO(...) do {} while (false)
#endif
#if ETK_MEM_DEBUG_LEVEL > 3
#define ETK_MEMORY_DEBUG(...) \
do { \
printf("[DEBUG] "); \
printf(__VA_ARGS__); \
printf("\n"); \
} while (false)
#else
#define ETK_MEMORY_DEBUG(...) do {} while (false)
#endif
#if ETK_MEM_DEBUG_LEVEL > 4
#define ETK_MEMORY_VERBOSE(...) \
do { \
printf("[VERBOSE] "); \
printf(__VA_ARGS__); \
printf("\n"); \
} while (false)
#else
#define ETK_MEMORY_VERBOSE(...) do {} while (false)
#endif
#if ETK_MEMORY_CHECKER > 1
// Max stric size of filename, variable Name, and fonction Name
#define ETK_MEM_MAX_STRING_SIZE (77)
#endif
/**
* @brief Class to save allocation elements
*/
class MemoryElementSystem {
public:
bool used; //!< for list system
char* pointerAllocated; //!< pointer really allocated
char* pointerGiveToUser; //!< pointer sent to the USER (in case of check of memory overflow)
size_t sizeUser; //!< User request size
size_t sizeAllocate; //!< data size really allocated by the tool
size_t sizeData; //!< current data size of allocated memory
size_t id; //!< Element ID to know the allocation Order
#if ETK_MEMORY_CHECKER > 1
const char* variableName; //!< Variable name when allocate
const char* functionName; //!< function name that allocate this buffer
const char* fileName; //!< function name that allocate this buffer
size_t functionLine; //!< function line where the buffer was allocated
#endif
};
class memoryAllocatorHandle {
private:
// to prevent double access:
pthread_mutex_t m_mutex;
#if ETK_MEMORY_CHECKER > 1
// Basic header to check the memory everflow (abstract element)
uint8_t* m_blockCheckMemory;
// To know the size of pre header and Post-header
uint32_t m_checkBorneSize;
#endif
// To do statictic memory allocation (Total of memory allocate from the start of program)
uint64_t m_totalMemAllocated;
// To do statictic memory allocation (Current size of allocated memory)
uint64_t m_currentMemAllocated;
// To do statictic memory allocation (Current size of allocated memory)
int64_t m_currentMemAllocatedCount;
int64_t m_currentMemAllocatedCountSize[64];
int64_t m_totalMemAllocatedCountSize[64];
// To do statictic memory allocation (Max of memory allocated in the same Time)
uint64_t m_maxMemoryAllocated;
// To do statictic memory allocation (number of allocation)
int64_t m_dynamicID;
// To know if this memory system is initialized
bool m_memSystemInitialize;
// List of element to remember allocate...
size_t m_memListElementSize;
MemoryElementSystem* m_memListElements;
public:
memoryAllocatorHandle():
m_mutex(PTHREAD_MUTEX_INITIALIZER),
#if ETK_MEMORY_CHECKER > 1
// Basic header to check the memory everflow (abstract element)
m_blockCheckMemory(null),
m_checkBorneSize(10*8),
#endif
m_totalMemAllocated(0),
m_currentMemAllocated(0),
m_currentMemAllocatedCount(0),
m_maxMemoryAllocated(0),
m_dynamicID(0),
m_memSystemInitialize(false),
m_memListElementSize(1024),
m_memListElements(null) {
#if ETK_MEMORY_CHECKER > 1
static const uint8_t blockCheckMemory[] = {
0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88,
0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
0x55, 0xAA, 0x5A, 0xA5, 0x11, 0xFF, 0x15, 0xB2,
0x55, 0xAA, 0x5A, 0xA5, 0x11, 0xFF, 0x15, 0xB2,
0x55, 0xAA, 0x5A, 0xA5, 0x11, 0xFF, 0x15, 0xB2,
0x55, 0xAA, 0x5A, 0xA5, 0x11, 0xFF, 0x15, 0xB2,
0x55, 0xAA, 0x5A, 0xA5, 0x11, 0xFF, 0x15, 0xB2,
0x55, 0xAA, 0x5A, 0xA5, 0x11, 0xFF, 0x15, 0xB2,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
};
m_blockCheckMemory = (uint8_t*)blockCheckMemory;
#endif
lock();
memset(m_totalMemAllocatedCountSize, 0, sizeof(m_totalMemAllocatedCountSize));
memset(m_currentMemAllocatedCountSize, 0, sizeof(m_currentMemAllocatedCountSize));
if (m_memSystemInitialize == true) {
return;
}
int systemRet;
if (m_memListElements == null) {
m_memListElements = new MemoryElementSystem[m_memListElementSize];
}
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
m_memListElements[iii].used = false;
}
m_memSystemInitialize = true;
unLock();
}
/**
* @brief Update statistique
* @param[in] _dataSize Allocated size
*/
void addMemory(size_t _dataSize) {
m_totalMemAllocated += _dataSize;
m_currentMemAllocated += _dataSize;
if (m_currentMemAllocated > m_maxMemoryAllocated) {
m_maxMemoryAllocated = m_currentMemAllocated;
}
m_currentMemAllocatedCount++;
for (int32_t iii=0; iii<64; ++iii) {
if (_dataSize <= (uint64_t(1) << iii)) {
m_totalMemAllocatedCountSize[iii]++;
break;
}
}
for (int32_t iii=0; iii<64; ++iii) {
if (_dataSize <= (uint64_t(1) << iii)) {
m_currentMemAllocatedCountSize[iii]++;
break;
}
}
}
void lock() {
pthread_mutex_lock(&m_mutex);
}
void unLock() {
pthread_mutex_unlock(&m_mutex);
}
/**
* @brief Update memory statistique
* @param[in] dataSize Removed size.
*/
void removeMemory(size_t _dataSize) {
m_currentMemAllocated -= _dataSize;
m_currentMemAllocatedCount--;
for (int32_t iii=0; iii<64; ++iii) {
if (_dataSize <= (uint64_t(1) << iii)) {
m_currentMemAllocatedCountSize[iii]--;
break;
}
}
}
/**
* @brief Get a current free element of the structure
* @return the free Element find or null
*/
MemoryElementSystem* getFreeElement() {
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
if (m_memListElements[iii].used == false) {
return &(m_memListElements[iii]);
}
}
// resize Linker size:
m_memListElementSize *= 2;
ETK_MEMORY_DEBUG("Realloate the allocator memory system: %ld", uint64_t(m_memListElementSize));
MemoryElementSystem* tmp = new MemoryElementSystem[m_memListElementSize];
if (tmp == null) {
m_memListElementSize /= 2;
return null;
}
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
tmp[iii].used = false;
}
memcpy(tmp, m_memListElements, sizeof(MemoryElementSystem) * m_memListElementSize / 2);
delete[] m_memListElements;
m_memListElements = tmp;
ETK_MEMORY_DEBUG("Realloate the allocator memory system: %ld (done)", uint64_t(m_memListElementSize));
// try again
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
if (m_memListElements[iii].used == false) {
return &(m_memListElements[iii]);
}
}
return null;
}
/**
* @brief Get the element structure reference if it existed
* @param[in] pointerAdresse pointer to retreave the element
* @return get the element reference for the curent adress pointer
*/
MemoryElementSystem *getAdressedElement(char* _pointerAdresse) {
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
if (m_memListElements[iii].used == true) {
if (m_memListElements[iii].pointerGiveToUser == _pointerAdresse) {
return &(m_memListElements[iii]);
}
}
}
return null;
}
#if ETK_MEMORY_CHECKER > 1
/**
* @brief Verify the curent Memory header
* This function vereify the memeory with the common header and header size.
* @param[in] pointerAdresse Start pointer to verify data
* @return the check result :
* - true : if an error existe
* - false : if no error
*/
bool checkMem(char* _pointerAdresse) {
uint8_t *pointer = (uint8_t*)_pointerAdresse;
for (size_t iii=0; iii<m_checkBorneSize; ++iii) {
if (*(pointer++) != m_blockCheckMemory[iii]) {
return true;
}
}
return false;
}
#endif
#if ETK_MEMORY_CHECKER > 1
/**
* @brief Display the current buffer to check error.
* Desactivated by debault (only for extreme debug)
* @param[in] _pointerAdresse pointer to start the print
* @param[in] _size number of char to display
*/
void displayBuffer(char* _pointerAdresse, uint32_t _size) {
/*
uint8_t *pointer = (uint8_t *)_pointerAdresse;
uint32_t i;
for (i=0; i<_size ;i++) {
if (i%50 == 0) {
printf("\n");
}
printf("%02X ", pointer[i]);
}
printf("\n");
*/
}
#endif
#if ETK_MEMORY_CHECKER > 1
/**
* @brief Get the filename (without all the Path)
* @param[in] _fileLink pointer on the name with the Path
* @return The last pointer of the filename
*/
const char *getFileName(const char* _fileLink) {
const char *element_2 = _fileLink;
const char *element_1 = _fileLink;
const char *element_0 = _fileLink;
const char * pch = null;
pch = _fileLink;
while (pch != null) {
element_2 = element_1;
element_1 = element_0;
element_0 = pch;
pch = strchr(pch+1, '/');
}
return element_2;
}
#endif
void displayMemoryProperty(MemoryElementSystem& _element) {
#if ETK_MEMORY_CHECKER > 1
bool errorOccured = false;
ETK_MEMORY_WARNING("Not FREE : %p ==> %p : %ld Bytes var=%s id=%ld",
_element.pointerAllocated,
_element.pointerGiveToUser,
_element.sizeUser,
(_element.variableName==null?"---":_element.variableName),
_element.id);
ETK_MEMORY_WARNING("%8d : %s() line=%ld file=%s",
(uint32_t)_element.id,
(_element.functionName==null?"---":_element.functionName),
_element.functionLine,
(_element.fileName==null?"---":_element.fileName));
if (checkMem(_element.pointerAllocated) == true) {
ETK_MEMORY_ERROR("MEM LOG (L): %s : %ld Bytes @ %p ==> user @ %p (depassement pre)",
(_element.variableName==null?"---":_element.variableName),
_element.sizeUser,
_element.pointerAllocated,
_element.pointerGiveToUser);
errorOccured = true;
}
if (checkMem(_element.pointerAllocated + _element.sizeUser + m_checkBorneSize) == true) {
ETK_MEMORY_ERROR("MEM LOG (L): %s : %ld Bytes @ %p ==> user @ %p (depassement post)",
(_element.variableName==null?"---":_element.variableName),
_element.sizeUser,
_element.pointerAllocated,
_element.pointerGiveToUser);
errorOccured = true;
}
if (errorOccured == true) {
displayBuffer(_element.pointerAllocated,
_element.sizeAllocate);
assert(false);
}
#else
ETK_MEMORY_WARNING("Not LOG : %p ==> %p : %ld Bytes",
_element.pointerAllocated,
_element.pointerGiveToUser,
uint64_t(_element.sizeUser));
#endif
}
uint64_t* createSnapshoot() {
lock();
size_t countElement = 0;
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
if (m_memListElements[iii].used == true) {
countElement++;
}
}
if (countElement == 0) {
unLock();
return null;
}
ETK_MEMORY_VERBOSE("find %ld element in memory", (uint64_t)countElement);
uint64_t* out = new uint64_t[countElement+10];
memset(out, 0, sizeof(uint64_t)*(countElement+10));
countElement = 0;
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
if (m_memListElements[iii].used == true) {
out[countElement++] = uint64_t(m_memListElements[iii].id);
}
}
unLock();
return out;
}
bool checkSnapshoot(uint64_t* _handle) {
if (_handle == null) {
return false;
}
lock();
bool haveError = false;
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
if (m_memListElements[iii].used == true) {
uint64_t* dataBase = _handle;
bool find = false;
size_t jjj = 0;
while (dataBase[jjj] != 0) {
if (dataBase[jjj] == uint64_t(m_memListElements[iii].id)) {
find = true;
break;
}
jjj++;
//dataBase++;
}
if (find == false) {
haveError = true;
displayMemoryProperty(m_memListElements[iii]);
}
}
}
unLock();
return haveError == false;
}
void flipID(void* _pointer1, void* _pointer2) {
MemoryElementSystem* handle1 = getAdressedElement((char*)_pointer1);
MemoryElementSystem* handle2 = getAdressedElement((char*)_pointer2);
if ( handle1 == null
|| handle2 == null) {
ETK_MEMORY_WARNING("MEM flip error %p %p", _pointer1, _pointer2);
return;
}
etk::swap(handle1->id, handle2->id);
}
void clearSnapshoot(uint64_t* _handle) {
if (_handle == null) {
return;
}
delete[] (uint64_t*)_handle;
}
void* allocate(size_t _num,
size_t _size,
const char* _variableName,
const char* _functionName,
int32_t _line,
const char* _fileName) {
MemoryElementSystem* myElement;
lock();
m_dynamicID++;
myElement = getFreeElement();
// check free handle
if (myElement != null) {
#if ETK_MEMORY_CHECKER > 1
const char *fileNameShort = null;
#endif
myElement->id = m_dynamicID;
// if an element is free :
myElement->sizeUser = _size * _num;
myElement->sizeData = _size;
#if ETK_MEMORY_CHECKER > 1
myElement->sizeAllocate = myElement->sizeUser + m_checkBorneSize*2;
myElement->variableName = _variableName;
myElement->functionName = _functionName;
myElement->fileName = _fileName;
//fileNameShort = getFileName(_fileName);
myElement->functionLine = _line;
#else
myElement->sizeAllocate = myElement->sizeUser;
#endif
myElement->pointerAllocated = null;
myElement->pointerGiveToUser = null;
// real allocation :
myElement->pointerAllocated = new char[myElement->sizeAllocate];
if (myElement->pointerAllocated != null) {
// set edded memory
addMemory(myElement->sizeUser);
// save curent pointer
#if ETK_MEMORY_CHECKER > 1
myElement->pointerGiveToUser = myElement->pointerAllocated + m_checkBorneSize;
#else
myElement->pointerGiveToUser = myElement->pointerAllocated;
#endif
ETK_MEMORY_VERBOSE("MEM allocate (L): %s : %ld Bytes @ %p ==> user @ %p id=%ld", _variableName, _num*_size, myElement->pointerAllocated, myElement->pointerGiveToUser, myElement->id);
// set bornes:
#if ETK_MEMORY_CHECKER > 1
memcpy(myElement->pointerAllocated, m_blockCheckMemory, m_checkBorneSize);
#endif
#if ETK_MEMORY_CHECKER > 1
memcpy(myElement->pointerAllocated + myElement->sizeUser + m_checkBorneSize, m_blockCheckMemory, m_checkBorneSize);
#endif
// add to the elements list
myElement->used = true;
} else {
ETK_MEMORY_VERBOSE("MEM allocate (L): %s : %ld Bytes @ (ERROR)", _variableName, uint64_t(myElement->sizeUser));
}
unLock();
// else : no memory allocated ==> nothing to save
return myElement->pointerGiveToUser;
} else {
// if no free handle:
void * localPointer = null;
localPointer = new char[_num * _size];
if (localPointer != null) {
if (_variableName == null) {
ETK_MEMORY_VERBOSE("MEM allocate (-): --- : %lu Bytes @ %p (No log...)", _num*_size, localPointer);
} else {
ETK_MEMORY_VERBOSE("MEM allocate (-): %s : %lu Bytes @ %p (No log...)", _variableName, _num*_size, localPointer);
}
// set edded memory
//addMemory(_num * _size); // not availlable can not un add memory
m_totalMemAllocated += _num * _size;
} else {
if (_variableName == null) {
ETK_MEMORY_VERBOSE("MEM allocate (-): --- : %lu Bytes @ (ERROR)", _num*_size);
} else {
ETK_MEMORY_VERBOSE("MEM allocate (-): %s : %lu Bytes @ (ERROR)", _variableName, _num*_size);
}
}
unLock();
return localPointer;
}
}
void remove(void* _pointerData, const char* _variableName, const char* _functionName, int32_t _line, const char* _fileName) {
MemoryElementSystem * myElement;
lock();
char* asyncFree = null;
myElement = getAdressedElement((char*)_pointerData);
// check free handle
if (myElement != null) {
bool errorOccured = false;
// We know this element :
#if ETK_MEMORY_CHECKER > 1
// check end and Start :
if (checkMem(myElement->pointerAllocated) == true) {
if (_variableName == null) {
ETK_MEMORY_ERROR("MEM free (L): --- : %ld Bytes @ %p ==> user @ %p (depassement pre)", uint64_t(myElement->sizeUser), myElement->pointerAllocated, myElement->pointerGiveToUser);
} else {
ETK_MEMORY_ERROR("MEM free (L): %s : %ld Bytes @ %p ==> user @ %p (depassement pre)", _variableName, uint64_t(myElement->sizeUser), myElement->pointerAllocated, myElement->pointerGiveToUser);
}
errorOccured = true;
}
if (checkMem(myElement->pointerAllocated + myElement->sizeUser + m_checkBorneSize) == true) {
if (_variableName == null) {
ETK_MEMORY_ERROR("MEM free (L): --- : %ld Bytes @ %p ==> user @ %p (depassement post)", uint64_t(myElement->sizeUser), myElement->pointerAllocated, myElement->pointerGiveToUser);
} else {
ETK_MEMORY_ERROR("MEM free (L): %s : %ld Bytes @ %p ==> user @ %p (depassement post)", _variableName, uint64_t(myElement->sizeUser), myElement->pointerAllocated, myElement->pointerGiveToUser);
}
errorOccured = true;
}
if (errorOccured == false) {
if (_variableName == null) {
ETK_MEMORY_VERBOSE("MEM free (L): --- : %ld Bytes @ %p ==> user @ %p", uint64_t(myElement->sizeUser), myElement->pointerAllocated, myElement->pointerGiveToUser);
} else {
ETK_MEMORY_VERBOSE("MEM free (L): %s : %ld Bytes @ %p ==> user @ %p", _variableName, uint64_t(myElement->sizeUser), myElement->pointerAllocated, myElement->pointerGiveToUser);
}
} else {
displayBuffer(myElement->pointerAllocated, myElement->sizeAllocate);
//ETK_ASSERT(1 == 0, "Memory error detected");
}
#else
if (_variableName == null) {
ETK_MEMORY_VERBOSE("MEM free (L): --- : %ld Bytes @ %p ==> user @ %p", uint64_t(myElement->sizeUser), myElement->pointerAllocated, myElement->pointerGiveToUser);
} else {
ETK_MEMORY_VERBOSE("MEM free (L): %s : %ld Bytes @ %p ==> user @ %p", _variableName, uint64_t(myElement->sizeUser), myElement->pointerAllocated, myElement->pointerGiveToUser);
}
#endif
asyncFree = myElement->pointerAllocated;
myElement->pointerAllocated = null;
removeMemory(myElement->sizeUser);
myElement->used = false;
}
unLock();
if (asyncFree != null) {
// free Buffer:
delete[] asyncFree;
return;
}
//Unknown element
if (_variableName == null) {
ETK_MEMORY_WARNING("MEM free (-): --- : ?? Bytes @ %p ==> unsaved element", _pointerData);
} else {
ETK_MEMORY_WARNING("MEM free (-): %s : ?? Bytes @ %p ==> unsaved element", _variableName, _pointerData);
}
lock();
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
if (m_memListElements[iii].used == false) {
if (m_memListElements[iii].pointerGiveToUser == _pointerData) {
ETK_MEMORY_ERROR("MEM free (D): --- : user @ %p (double 'free' detected)", m_memListElements[iii].pointerGiveToUser);
}
}
}
unLock();
delete (char*)_pointerData;
}
void displayMemorySize(size_t _size, const char* _name) {
if (_size > 1024*1024*1024) {
uint32_t teraByte = _size/(1024*1024*1024);
uint32_t megaByte = (_size/(1024*1024)%1024);
uint32_t kiloByte = (_size/1024) % 1024;
uint32_t byte = _size % 1024;
ETK_MEMORY_DEBUG("MEM : %s: %4dT %4dM %4dk %4dB", _name, teraByte, megaByte, kiloByte, byte);
} else if (_size > 1024*1024) {
uint32_t megaByte = _size/(1024*1024);
uint32_t kiloByte = (_size/1024) % 1024;
uint32_t byte = _size % 1024;
ETK_MEMORY_DEBUG("MEM : %s: %4dM %4dk %4dB", _name, megaByte, kiloByte, byte);
} else if (m_totalMemAllocated > 1024) {
uint32_t megaByte = _size/(1024*1024);
uint32_t kiloByte = (_size/1024) % 1024;
uint32_t byte = _size % 1024;
ETK_MEMORY_DEBUG("MEM : %s: %4dk %4dB", _name, kiloByte, byte);
} else {
uint32_t megaByte = _size/(1024*1024);
uint32_t kiloByte = (_size/1024) % 1024;
uint32_t byte = _size % 1024;
ETK_MEMORY_DEBUG("MEM : %s: %4dB", _name, byte);
}
}
void display(bool _statusOnly) {
lock();
ETK_MEMORY_DEBUG("MEM: Log : ------------------------------");
ETK_MEMORY_DEBUG("MEM: (current/total) allocation: %ld / %ld ", int64_t(m_currentMemAllocatedCount), uint64_t(m_dynamicID));
for (int32_t iii=0; iii<64; ++iii) {
if (m_currentMemAllocatedCountSize[iii] != 0) {
ETK_MEMORY_DEBUG("MEM: Number (current/Total) of allocation: 2<<%2d: %8ld / %8ld %9ld Bytes",
iii,
uint64_t(m_currentMemAllocatedCountSize[iii]),
uint64_t(m_totalMemAllocatedCountSize[iii]),
(uint64_t(1)<<iii));
}
}
ETK_MEMORY_DEBUG("MEM: number of element that can be registered %ld", m_memListElementSize);
displayMemorySize(m_memListElementSize*sizeof(MemoryElementSystem) + sizeof(memoryAllocatorHandle), "System allocator ");
displayMemorySize(m_totalMemAllocated, "Total allocated ");
displayMemorySize(m_currentMemAllocated, "Total Current Use ");
displayMemorySize(m_maxMemoryAllocated, "Max simultaneous Use ");
if (_statusOnly == true) {
unLock();
return;
}
ETK_MEMORY_DEBUG("MEM : Log : ----------- Memory -----------");
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
if (m_memListElements[iii].used == true) {
displayMemoryProperty(m_memListElements[iii]);
}
}
ETK_MEMORY_DEBUG("MEM : -----------------------------------");
unLock();
}
bool check() {
bool detectError = false;
lock();
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
if (m_memListElements[iii].used == true) {
#if ETK_MEMORY_CHECKER > 1
bool errorOccured = false;
if (checkMem(m_memListElements[iii].pointerAllocated) == true) {
const char* tmp = m_memListElements[iii].variableName;
if (tmp == null) {
tmp = "---";
}
ETK_MEMORY_ERROR("MEM CHECK (L): %s : %ld Bytes @ %p ==> user @ %p (depassement pre)", tmp, uint64_t(m_memListElements[iii].sizeUser), m_memListElements[iii].pointerAllocated, m_memListElements[iii].pointerGiveToUser);
errorOccured = true;
}
if (checkMem(m_memListElements[iii].pointerAllocated + m_memListElements[iii].sizeUser + m_checkBorneSize) == true) {
const char* tmp = m_memListElements[iii].variableName;
if (tmp == null) {
tmp = "---";
}
ETK_MEMORY_ERROR("MEM CHECK (L): %s : %ld Bytes @ %p ==> user @ %p (depassement post)", tmp, uint64_t(m_memListElements[iii].sizeUser), m_memListElements[iii].pointerAllocated, m_memListElements[iii].pointerGiveToUser);
errorOccured = true;
}
if (errorOccured == true) {
detectError = true;
displayBuffer(m_memListElements[iii].pointerAllocated, m_memListElements[iii].sizeAllocate);
// Clean all the erreor to prevent the other error display
memcpy(m_memListElements[iii].pointerAllocated, m_blockCheckMemory, m_checkBorneSize);
// Clean all the erreor to prevent the other error display
memcpy(m_memListElements[iii].pointerAllocated + m_memListElements[iii].sizeUser + m_checkBorneSize, m_blockCheckMemory, m_checkBorneSize);
}
#endif
}
}
unLock();
return detectError;
}
bool checkPointer(void* _pointer) {
lock();
for (size_t iii=0; iii<m_memListElementSize; ++iii) {
if (m_memListElements[iii].used == true) {
bool find = false;
if (m_memListElements[iii].pointerAllocated == _pointer) {
find = true;
}
if (m_memListElements[iii].pointerGiveToUser == _pointer) {
find = true;
}
if (find == true) {
unLock();
return true;
}
}
}
unLock();
ETK_MEMORY_ERROR("MEM Check pointer: Can not find the pointer in the system DB...");
return false;
}
};
// This permit to initialize the handle just in time ...
static memoryAllocatorHandle& getHandle() {
static memoryAllocatorHandle tmp;
return tmp;
}
uint64_t* etk::memory::createSnapshoot() {
return getHandle().createSnapshoot();
}
bool etk::memory::checkSnapshoot(uint64_t* _handle) {
return getHandle().checkSnapshoot(_handle);
}
void etk::memory::clearSnapshoot(uint64_t* _handle) {
getHandle().clearSnapshoot(_handle);
}
void etk::memory::flipID(void* _pointer1, void* _pointer2) {
getHandle().flipID(_pointer1, _pointer2);
}
void* etk::memory::allocate(size_t _num,
size_t _size,
const char* _variableName,
const char* _functionName,
int32_t _line,
const char* _fileName) {
return getHandle().allocate(_num, _size, _variableName, _functionName, _line, _fileName);
}
void etk::memory::remove(void* _pointerData, const char* _variableName, const char* _functionName, int32_t _line, const char* _fileName) {
getHandle().remove(_pointerData, _variableName, _functionName, _line, _fileName);
}
void etk::memory::display(bool _statusOnly) {
getHandle().display(_statusOnly);
}
bool etk::memory::check() {
return getHandle().check();
}
bool etk::memory::checkPointer(void* _pointer) {
return getHandle().checkPointer(_pointer);
}
#endif