J'ai un programme ca qui ressemble à ça
principal c
#include <stdio.h>
#define SOME_VAR 10
static int heap[SOME_VAR];
int main(void) {
printf("%p", heap);
return 0;
}
et sort cela lorsque j'exécute le programme compilé plusieurs fois
0x58aa7c49060
0x56555644060
0x2f8d1f8e060
0x92f58280060
0x59551c53060
0xd474ed6e060
0x767c4561060
0xf515aeda060
0xbe62367e060
Pourquoi ça finit toujours en 060? Et le tableau est-il stocké en tas?
Edit: je suis sur Linux et j'ai ASLR sur. J'ai compilé le programme en utilisant gcc
Réponses:
Les adresses diffèrent en raison de l'ASLR (ramdomisation de la disposition de l'espace d'adressage). En utilisant cela, le binaire peut être mappé à différents emplacements dans l'espace d'adressage virtuel.
heap
Contrairement à son nom, la variable n'est pas située sur le tas, mais sur lebss
. Le décalage dans l'espace d'adressage est donc constant.Les pages sont mappées avec une granularité de page, qui est de 4096 octets (hex: 0x1000) sur de nombreuses plates-formes. C'est la raison pour laquelle les trois derniers chiffres hexadécimaux de l'adresse sont les mêmes.
Lorsque vous avez fait de même avec une variable de pile , l'adresse peut même varier dans les derniers chiffres sur certaines plates-formes (à savoir Linux avec des noyaux récents), car la pile n'est pas seulement mappée ailleurs, mais reçoit également un décalage aléatoire au démarrage.
la source
heap
alors qu'elle n'est pas en tas?060
.Si vous utilisez Windows, la raison en est la structure PE .
Votre
heap
variable est stockée dans une.data
section de fichier et son adresse est calculée en fonction du début de cette section. Chaque section est chargée dans une adresse indépendamment, mais son adresse de départ est multiple de la taille de la page. Parce que vous n'avez pas d'autres variables, son adresse est probablement le début de la.data
section, donc son adresse sera multiple de la taille du bloc.Par exemple, voici le tableau de la version Windows compilée de votre code: La
.text
section est où se trouve votre code compilé et.data
contient votreheap
variable. Lorsque votre PE est chargé en mémoire, les sections sont chargées à des adresses différentes et retournées parVirtualAlloc()
et seront multiples de taille de page. Mais l'adresse de chaque variable est relative au début de la section qui est maintenant une taille de page. Ainsi, vous verrez toujours un nombre fixe sur les chiffres inférieurs. Étant donné que l'adresse relativeheap
du début de la section est basée sur le compilateur, les options de compilation, etc., vous verrez un nombre différent du même code mais des compilateurs différents, mais à chaque fois ce qui sera imprimé est fixe.Lorsque je compile du code, j'ai remarqué qu'il
heap
est placé sur des0x8B0
octets après le début de la.data
section. Donc, chaque fois que j'exécute ce code, mon adresse se termine0x8B0
.la source
heap
alors qu'elle n'est pas en tas?Le compilateur est arrivé à mettre
heap
à l'offset 0x60 octets dans un segment de données qu'il possède, probablement parce que le compilateur a d'autres éléments dans les premiers octets 0x60, tels que les données utilisées par le code qui démarre lamain
routine. C'est pourquoi vous voyez «060»; c'est exactement là où cela s'est passé, et cela n'a pas beaucoup d'importance.La randomisation de la configuration de l'espace d'adressage modifie la ou les adresses de base utilisées pour diverses parties de la mémoire du programme, mais elle le fait toujours en unités de 0x1000 octets (car cela évite de causer des problèmes d'alignement et d'autres problèmes). Vous voyez donc que les adresses fluctuent par multiples de 0x1000, mais les trois derniers chiffres ne changent pas.
La définition
static int heap[SOME_VAR];
définitheap
avec la durée de stockage statique. Les implémentations C typiques le stockent dans une section de données générales, pas dans le tas. Le «tas» est un terme impropre pour la mémoire qui est utilisée pour l'allocation dynamique. (Il s'agit d'un terme impropre car lesmalloc
implémentations peuvent utiliser une variété de structures de données et d'algorithmes, non limités aux tas. Ils peuvent même utiliser plusieurs méthodes dans une seule implémentation.)la source