En plus des problèmes de base Ned Batchelder a souligné, un problème beaucoup plus subtile est qu'un allocateur doit retourner une adresse qui est correctement aligné pour tout objet est alloué. Sur certaines plates-formes (x86), cela peut ne pas avoir d'importance, sauf pour les problèmes de performances, mais sur de nombreuses plates-formes, c'est un briseur d'accord complet.
J'ai également dû effectuer un cast (char*)
pour effectuer l'arithmétique de pointeur stack
(vous ne pouvez pas faire d'arithmétique de pointeur sur les types void*
).
Et vous devriez mettre parens autour de l'expression dans la macro MAX_MEMORY
. Je ne pense pas qu'il y ait des problèmes de préséance que vous auriez sans eux, car tous les opérateurs de haute priorité que la multiplication ne serait pas de toute façon une syntaxe correcte. Avec les macros, c'est toujours mieux mieux vaut prévenir que guérir. (Il existe au moins une exception où l'opérateur []
peut se lier uniquement au 2
et non pas à l'expression entière MAX_MEMORY
, mais ce serait une situation très étrange de voir MAX_MEMORY[arrayname]
, même si elle est syntaxiquement valide).
En fait, j'en aurais fait une énumération.
Vous pouvez probablement garder le allocateur simple, en retournant un bloc de mémoire qui est correctement aligné pour tout type de données de base sur le système (peut-être un alignement de 8 octets):
/* 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;
}
Je n'appellerais pas l'arène de la mémoire "pile". Votre implémentation actuelle est comme une pile, oui, mais si vous voulez que cela fonctionne comme malloc, avec free, alors c'est un tas. –
Merci beaucoup les gars pour tous vos commentaires! – Radek
Cet allocateur est le début de ce que l'on appelle un 'allocateur de pool' - les allocations se produisent comme ci-dessus, puis le bloc entier est immédiatement libéré dans le système lorsque l'unité de travail utilisant le pool est terminée. Il aide à gérer les fuites causées par la gestion séparée de chaque petite allocation. Apache utilise des pools - une requête HTTP arrive, un pool est configuré pour la requête, une fois la requête terminée, le pool est libéré. Rien d'autre travaillant sur la requête ne doit s'inquiéter de libérer des objets alloués dynamiquement. –