2009-08-26 9 views
3

Y at-il une telle chose? Je veux dire une fonction qui réallouerait la mémoire sans la déplacer si possible ou ne ferait rien si ce n'est pas possible. En Visual C il y a _expand qui fait ce que je veux. Quelqu'un connaît-il les équivalents pour d'autres plateformes, en particulier gcc/linux? Je suis surtout intéressé par la réduction de la mémoire sur place lorsque cela est possible (et le realloc standard peut déplacer la mémoire même lorsque sa taille diminue, au cas où quelqu'un le demanderait).realloc en place avec gcc/linux

Je sais qu'il n'y a pas de façon standard de le faire, et je demande explicitement des astuces hackish sales dépendantes de l'implémentation. Listez tout ce que vous savez qui fonctionne quelque part.

Répondre

1

Une question similaire a été posée sur another forum. L'une des réponses les plus raisonnables que j'ai vu impliqué en utilisant mmap pour l'allocation initiale (en utilisant le drapeau MAP_ANONYMOUS) et en appelant mremapsans le drapeau MREMAP_MAYMOVE. Cependant, une limitation de cette approche est que les tailles d'allocation doivent être des multiples exacts à la taille de la page du système.

2

Outre l'utilisation mmap et munmap pour éliminer l'excès que vous n'avez pas besoin (ou mremap, ce qui pourrait faire la même chose mais non standard), il n'y a pas moyen de réduire la taille d'un bloc de mémoire alloué. Et mmap a la granularité de la page (normalement 4k) donc à moins que vous ayez affaire à de très gros objets, l'utiliser serait pire que de simplement laisser les objets surdimensionnés et de ne pas les rétrécir du tout. Cela dit, rétrécir la mémoire in-situ n'est probablement pas une bonne idée, car la mémoire libérée sera très fragmentée. Une bonne implémentation realloc voudra déplacer des blocs en les rétrécissant significativement comme une opportunité de défragmenter la mémoire.

Je suppose que votre situation est que vous avez un bloc de mémoire alloué avec beaucoup d'autres structures contenant des pointeurs, et vous ne voulez pas invalider ces pointeurs. Si tel est le cas, voici une solution générale:

  1. Cassez votre objet redimensionnable en deux allocations, un objet « tête » de taille fixe qui pointe vers le second objet de taille variable.
  2. Pour les autres objets qui doivent pointer sur l'objet de taille variable, de stocker un pointeur à l'objet de tête et un nombre entier de décalage (size_t ou ptrdiff_t) dans l'objet de taille variable.

Maintenant, même si l'objet de taille variable se déplace vers une nouvelle adresse, aucune de ses références n'est invalidée. Si vous utilisez ces objets à partir de plusieurs threads, vous devez placer un verrou en lecture-écriture dans l'objet head, le verrouiller en lecture lorsque vous devez accéder à l'objet de taille variable et le verrouiller en écriture lors du redimensionnement l'objet de taille variable.