Si necesita implementar una asignación estilo malloc en el PIC u otro microcontrolador pequeño, hay algunas maneras de hacerlo. Lo más sencillo es definir:
#define POOL_SIZE 100 // Or however big it can be without running out of space
uint8_t mem_pool[POOL_SIZE];
#define pool_end (mem_pool+POOL_SIZE)
uint8_t *next_alloc;
void *malloc(uint8_t size)
{
if (pool_end - next_alloc <= size)
{
uint8_t *ret = next_alloc;
next_alloc += size;
return ret;
}
else
return 0;
}
void release(uint8_t *dat)
{
next_alloc = dat;
}
Liberar cualquier objeto liberaría ese objeto y todo lo que se liberó después de él . En los casos en que esto coincida con la semántica deseada, el código anterior sería mucho más barato que admitir la asignación y liberación de memoria en una secuencia arbitraria. Si se pueden dividir las asignaciones en dos grupos y decir que es aceptable que la liberación de un objeto también libere todos los demás objetos en el mismo grupo , eso simplemente requiere que pool_end
sea un uint8_t *
variable, y luego agregar:
void *umalloc(uint8_t size)
{
if (pool_end - next_alloc <= size)
{
pool_end -= size;
return pool_end;
}
else
return 0;
}
void urelease(uint8_t *dat, uint8_t size)
{
pool_end = dat+size;
}
Tenga en cuenta que a la función urelease
, a diferencia de release
, se le debe indicar el tamaño del bloque que se asignó, pero la sobrecarga total para estos enfoques será de 2 bytes si se usa solo malloc/release
y 4 bytes si utilizando umalloc/urelease
, sin sobrecarga por bloque adicional .
Si uno necesita asignar y liberar bloques en una secuencia arbitraria, es posible que un PIC lo admita, pero hacerlo agregará complejidad y puede resultar en una fragmentación de la memoria. Si por ejemplo uno tiene un grupo de 512 bytes y asigna 16 elementos cuyos tamaños son alternativamente 27 + 1 bytes y 3 + 1 bytes (27 o 3 bytes de datos, más un encabezado de un byte) y uno libera todos los 27 + 1 bytes elementos, a uno le quedarían 448 bytes, pero no tienen espacio que pueda contener 28 bytes de datos. Si se puede trabajar con las limitaciones del grupo de doble terminación que se muestra arriba, dicho diseño tendrá una sobrecarga mínima y requerirá un código mínimo para su uso, pero permitirá que la memoria se divida entre diferentes propósitos en tiempo de ejecución.