2016-01-20 4 views
8

J'ai demandé à Google et fait des recherches sur StackOverflow. Ma question est que quand j'entre la fonction main() dans un programme C++ et déclare la toute première variable, pourquoi est-ce que l'adresse de cette variable peut varier selon différentes exécutions? S'il vous plaît voir mon exemple programme ci-dessous:Pourquoi les adresses des variables locales peuvent-elles être différentes à chaque fois?

#include <iostream> 

int main() { 
    int *a = new int; 
    int *b = new int; 

    std::cout << "address: " << a << " " << b << std::endl; 
    std::cout << "address of locals: " << &a << " " << &b << std::endl; 
    return 0; 
} 

Résultat sur l'exécution 1:

address: 0xa32010 0xa32030 
address of locals: 0x7fff10de2cf0 0x7fff10de2cf8 

Résultat sur l'exécution 2:

address: 0x1668010 0x1668030 
address of locals: 0x7ffc252ccd90 0x7ffc252ccd98 

Résultat sur l'exécution 3:

address: 0x10e0010 0x10e0030 
address of locals: 0x7ffd3d2cf7f0 0x7ffd3d2cf7f8 

Comme vous pouvez le voir, j'obtiens des résultats différents sur différentes exécutions. La première ligne de la sortie correspondant à l'adresse de la mémoire allouée, qui devrait arriver dans le tas - si on leur attribue des adresses différentes à chaque fois, cela me semble logique. Cependant, même lorsque j'imprime les adresses de variables locales - correspondant à la deuxième ligne - les résultats sont toujours différents. À première vue, je pensais que c'était parce que le programme imprimait une adresse de mémoire physique, mais ce message, Virtual Memory or Physical Memory, réfute ma pensée initiale. Y a-t-il une raison quelconque, étant donné que l'exécution des programmes est "identique", sans threading, sans entrée d'utilisateur, etc., qu'il existe toujours des allocations de mémoire avec des adresses différentes?

environnement Test:

  • Linux 14,04
  • Mac OS X 10,10
+13

Pour un, ASLR contribue probablement - est-il activé dans les noyaux sur vos systèmes de test? – fish2000

+2

Oui, c'est presque certainement [ASLR] (https://en.wikipedia.org/wiki/Address_space_layout_randomization) au travail. –

+1

@ fish2000, vous devriez certainement ajouter ceci comme une réponse avec un peu d'explication. – SergeyA

Répondre

11

Lors de l'attribution sur le tas (en utilisant l'opérateur new ou malloc() et amis), votre programme doit demandez au système d'exploitation d'allouer votre mémoire de tas. Beaucoup de choses dans les coulisses se produisent dans le gestionnaire de mémoire du système d'exploitation (dont les détails de mise en œuvre sont principalement au-dessus de mon niveau de rémunération: collecte des ordures, consolidation de la mémoire récupérée, etc). penses-y.

Les variables locales sont allouées sur la pile. Traditionnellement, l'attribution des piles serait répétable, mais cela a changé au cours des dernières années. Address space layout randomization (ASR) est une innovation relativement récente dans la gestion de la mémoire OS, qui rend délibérément les adresses de mémoire dans les allocations de pile (comme celles que vous avez observées) aussi déterministes que possible au moment de l'exécution. C'est une fonctionnalité de sécurité: cela empêche les mauvais acteurs d'exploiter les débordements de mémoire tampon, car si l'implémentation de l'ASLR est suffisamment entropique, qui sait ce qu'il va y avoir à la fin du tampon de débordement?

Le prix que vous payez pour ceci et d'autres fonctionnalités de gestion de la mémoire est le contrôle. Parier sur les adresses des allocations sur une plateforme moderne (non intégrée), c'est comme jouer à Powerball: peut-être une distraction amusante mais pas un plan réalisable pour l'avenir. Si votre code fonctionne sur une plate-forme AVR-ISA ou quelque chose comme ça, peut-être que les chances sont assez proches de Blackjack de sorte que quelqu'un pourrait être incité à jouer pour gagner (pour ainsi dire).De toute façon, je ne suis pas un joueur de jeu, personnellement - comme je le dis souvent, les messieurs préfèrent l'allocation de pile. Mais c'est essentiellement pourquoi vous obtenez ces résultats.

Merci à @ T.C. pour le lien et @SergeyA pour la suggestion.

+4

Incidemment, ASLR s'applique également à l'emplacement de la pile, ce qui explique pourquoi les variables locales ont également des adresses différentes à chaque exécution. Ce qui est vraiment ce que la question devenait. –

+0

@JordanMelo bon point - J'ai supposé une compréhension occasionnelle des termes comme par ex. "Stack" et "heap" dans la réponse - mais oui la pile d'un programme est en effet elle-même initialisée par le gestionnaire de mémoire en utilisant ASLR et je voulais vraiment mentionner ce fait, merci – fish2000

+1

Quand vous parlez d'ASLR comme un élément de sécurité, avez-vous signifie qu'il protège contre les débordements de tampon basés sur la pile (et pas tas)? Je suppose que c'est la principale vulnérabilité à laquelle elle répond. – Banex