@ -5,6 +5,38 @@
# include "memory_pool.h"
# include "mem.h"
# define POOL_CANARY_OFF (pool->object_size)
# define POOL_TAG_OFF (pool->object_size + 1)
# define POOL_ALLOC_SIZE (pool->object_size + 2)
# define POOL_CANARY_VAL 0xAA
static void pool_init_tags ( struct memory_pool * pool , void * obj )
{
uint8_t * canary = ( uint8_t * ) obj + POOL_CANARY_OFF ;
uint8_t * counter = ( uint8_t * ) obj + POOL_TAG_OFF ;
* canary = POOL_CANARY_VAL ;
* counter = + + pool - > alloc_tag_counter ;
if ( pool - > alloc_tag_counter = = 0 ) pool - > alloc_tag_counter = 1 ;
}
static void pool_check_and_clear_tags ( struct memory_pool * pool , void * obj , const char * location )
{
uint8_t * canary = ( uint8_t * ) obj + POOL_CANARY_OFF ;
uint8_t * counter = ( uint8_t * ) obj + POOL_TAG_OFF ;
if ( * canary ! = POOL_CANARY_VAL ) {
DEBUG_ERROR ( DEBUG_CATEGORY_MEMORY , " pool_free BUFFER OVERFLOW %p canary=0x%02x from %s! halting " , obj , * canary , location ) ;
volatile int _halt = 1 ;
while ( _halt ) { }
}
if ( * counter = = 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_MEMORY , " pool_free DOUBLE FREE %p from %s! halting " , obj , location ) ;
volatile int _halt = 1 ;
while ( _halt ) { }
}
* counter = 0 ;
}
static size_t g_total_free = 0 ;
size_t memory_pool_get_total_free_blocks ( void ) {
@ -22,6 +54,7 @@ struct memory_pool* memory_pool_init(size_t object_size) {
pool - > free_count = 0 ;
pool - > allocations = 0 ;
pool - > reuse_count = 0 ;
pool - > alloc_tag_counter = 1 ;
return pool ;
}
@ -33,18 +66,21 @@ void* memory_pool_alloc_impl(struct memory_pool* pool, const char* location) {
if ( pool - > free_head ) {
void * obj = pool - > free_head ;
pool - > free_head = * ( void * * ) obj ; // Извлекаем next из начала блока
pool - > free_head = * ( void * * ) obj ;
pool - > free_count - - ;
g_total_free - - ;
pool - > reuse_count + + ;
memset ( obj , 0 , pool - > object_size ) ; // Опционально: очищаем память для безопасности
memset ( obj , 0 , pool - > object_size ) ;
pool_init_tags ( pool , obj ) ;
DEBUG_INFO ( DEBUG_CATEGORY_MEMORY , " pool_alloc reused: %s, remaining=%zu " , location , pool - > free_count ) ;
return obj ;
}
pool - > allocations + + ;
DEBUG_INFO ( DEBUG_CATEGORY_MEMORY , " pool_alloc: %s, total_allocs=%zu " , location , pool - > allocations ) ;
return u_calloc_impl ( 1 , pool - > object_size , location ) ; // Используем calloc для инициализации нулями
void * obj = u_calloc_impl ( 1 , POOL_ALLOC_SIZE , location ) ;
if ( obj ) pool_init_tags ( pool , obj ) ;
return obj ;
}
// Освободить объект в пул или в free
@ -53,9 +89,10 @@ void memory_pool_free_impl(struct memory_pool* pool, void* obj, const char* loca
return ;
}
// Если пул не заполнен, сохранить объект для повторного использования
pool_check_and_clear_tags ( pool , obj , location ) ;
if ( pool - > free_count < MEMORY_POOL_MAX_FREE ) {
* ( void * * ) obj = pool - > free_head ; // Сохраняем next в начало блока
* ( void * * ) obj = pool - > free_head ;
pool - > free_head = obj ;
pool - > free_count + + ;
g_total_free + + ;
@ -63,7 +100,6 @@ void memory_pool_free_impl(struct memory_pool* pool, void* obj, const char* loca
return ;
}
// Иначе освободить через free
DEBUG_INFO ( DEBUG_CATEGORY_MEMORY , " pool_free direct: %s " , location ) ;
u_free_impl ( obj , location ) ;
}