Además de los problemas básicos Ned Batchelder señaló, un problema mucho más sutil es que un asignador tiene que devolver una dirección que está correctamente alineado para cualquier objeto que está siendo asignado. En algunas plataformas (x86) esto puede no importar, excepto por problemas de rendimiento, pero en muchas plataformas es un factor decisivo.
También tuve que realizar un molde (char*)
para realizar la aritmética del puntero stack
(no se puede hacer la aritmética del puntero en los tipos void*
).
Y debe poner parens alrededor de la expresión en la macro MAX_MEMORY
. No creo que haya ningún problema de precedencia en el que te metas sin ellos, ya que todos los operadores de alta precedencia que la multiplicación no serían la sintaxis correcta de todos modos. Con macros, es siempre mejor que lo siento. (Hay al menos una excepción en la que el operador []
podría vincular solo a la expresión 2
y no a toda MAX_MEMORY
, pero sería una situación muy extraña ver MAX_MEMORY[arrayname]
, incluso si es sintácticamente válida).
De hecho, lo hubiera convertido en una enumeración.
probablemente Puede mantener el asignador sencilla mediante la devolución de un bloque de memoria que está correctamente alineado para cualquier tipo de datos básicos sobre el sistema (tal vez una alineación de 8 bytes):
/* Note: the following is untested */
/* it includes changes suggested by Batchelder */
#include <stdio.h>
#include <unistd.h>
enum {
kMaxMemory = 1024 * 1024 * 2, /* 2MB of memory */
kAlignment = 8
};
void *stack = NULL; /* pointer to available stack */
void * memoryAlloc(size_t size) {
void *pointer;
size = (size + kAlignment - 1) & ~(kAlignment - 1); /* round size up so allocations stay aligned */
if (stack == NULL)
stack = sbrk(kMaxMemory); /* give us system memory */
pointer = stack; /* we always have space :) */
stack = (char*) stack + size; /* move in stack forward as space allocated */
return pointer;
}
No llamaría a la arena de la memoria "pila". Su implementación actual es como una pila, sí, pero si tiene la intención de que funcione como lo hace malloc, con free, entonces es un montón. –
Muchas gracias chicos por todos sus comentarios! – Radek
Este asignador es el comienzo de algo llamado 'asignador de grupo' - las asignaciones ocurren como las anteriores, luego todo el bloque se libera de vuelta al sistema de una vez cuando se completa la unidad de trabajo que utiliza el grupo. Ayuda a lidiar con fugas causadas por tener que administrar cada pequeña asignación por separado. Apache utiliza pools: entra una solicitud HTTP, se configura un pool para la solicitud, cuando se completa la solicitud, se libera el pool. Nada más que trabaje en la solicitud debe preocuparse por liberar objetos asignados dinámicamente. –