Cela peut sembler une question très fondamentale, mais cela m’a été dans ma tête:
Lorsque nous allouons une variable locale, elle entre dans la pile. De la même manière, l'allocation dynamique entraîne le passage de la variable sur le tas. Ma question est la suivante: cette variable est-elle réellement sur une pile ou sur un tas, ou bien nous allons simplement faire référence à la pile et à Heap.
Par exemple,
Supposons que je déclare une variable int i
. Maintenant, cette i
est allouée sur la pile. Donc, quand j'imprimer l'adresse de i
, ce sera l'un des emplacement sur la pile? Même question pour le tas aussi.
Je ne suis pas tout à fait sûr de ce que vous demandez, mais je ferai de mon mieux pour vous répondre.
Ce qui suit déclare une variable i
sur la pile:
int i;
Lorsque je demande une adresse à l'aide de &i
, j'obtiens l'emplacement réel sur la pile.
Lorsque j'alloue quelque chose de manière dynamique en utilisant malloc
, il y a en fait DEUX données stockées. La mémoire dynamique est allouée sur le tas et le pointeur lui-même est alloué sur la pile. Donc dans ce code:
int* j = malloc(sizeof(int));
Cela alloue de l'espace sur le tas pour un entier. C'est également allouer de l'espace sur la pile pour un pointeur (j
). La valeur de la variable j
est définie sur l'adresse renvoyée par malloc
.
Espérons que ce qui suit est utile:
void foo()
{
// an integer stored on the stack
int a_stack_integer;
// a pointer to integer data, the pointer itself is stored on the stack
int *a_stack_pointer;
// make a_stack_pointer "point" to integer data that's allocated on the heap
a_stack_pointer = (int*)malloc(10 * sizeof(int));
}
Dans le cas de variables de pile, la variable elle-même (les données réelles) est stockée dans la pile.
Dans le cas de la mémoire allouée au segment de mémoire, les données sous-jacentes sont toujours stockées sur le segment de mémoire. Un pointeur sur cette mémoire/data peut être stocké localement sur la pile.
J'espère que cela t'aides.
La variable de pointeur elle-même résiderait sur la pile. La mémoire indiquée par le pointeur réside sur le tas.
int *i = malloc(sizeof(int));
i
résiderait sur la pile, la mémoire réelle sur laquelle je pointe *i
serait sur le tas.
Je suis d'accord avec Chris. Juste une autre façon d'expliquer ça. Considérons le code suivant:
int* j = malloc(sizeof(int));
free(j);
Même après avoir utilisé free (j), qui devrait libérer la mémoire du tas, le pointeur existe toujours et nous devons explicitement le rendre NULL. Cela suggère clairement qu'il existe également une contrepartie de pile du pointeur, sinon il aurait dû être inexistant après la commande free. Cette variable de pile est celle qui pointe vers l'adresse du tas où la mémoire a été allouée dynamiquement à l'aide de malloc.
La réponse de M. Eberle est correcte à 100%, mais puisque Google l'a indiqué comme première réponse lors de la recherche de malloc heap or stack
, je dois ajouter que malloc()
alloue les données sur le tas le plus à l'heure actuelle. Si les données allouées étaient supérieures à MMAP_THRESHOLD
, qui correspond généralement à 128 Ko sur des systèmes 32 bits, malloc()
utilisera not et utilisera le tas et allouera les données dans un segment de mémoire anonyme situé généralement sous la pile, poussant dans le sens d'une mémoire insuffisante.
C'est la même région que celle où se trouvent les bibliothèques chargées dynamiquement (libc.so
, etc.). Voici le passage pertinent de man malloc
:
En règle générale, malloc () alloue de la mémoire à partir du tas et ajuste la taille Du tas selon les besoins, à l'aide de sbrk (2). Lors de l'allocation de blocs De mémoire supérieurs à MMAP_THRESHOLD octets, l'implémentation Glibc malloc () alloue la mémoire en tant que mappage anonyme privé à l'aide de mmap (2). MMAP_THRESHOLD est de 128 Ko par défaut, , Mais est réglable à l'aide de mallopt (3). Avant Linux 4.7, les attributions effectuées à l'aide de mmap (2) n'étaient pas affectées par la limite de ressources RLIMIT_DATA; depuis Linux 4.7, cette limite est également imposée pour les allocations effectuées à l'aide de mmap (2).
Comme exemple pratique, n'hésitez pas à consulter le message suivant . Il alloue essentiellement 300 Ko avec malloc()
, puis exécute pmap <PID>
pour afficher le segment de mémoire approprié.
pile ou tas ne sont pas des mémoires séparées, ce sont des segments de mémoire auxquels un programme en cours est alloué par le système, mais différentes manières d’organiser les données en mémoire.
Ainsi, lorsque vous obtenez & i, il s’agit d’une adresse mémoire, aussi simple que cela.