2016-01-20 26 views
8

Poprosiłem Google o przeprowadzenie badań nad StackOverflow. Moje pytanie brzmi: kiedy wprowadzam funkcję main() w programie C++ i deklaruję pierwszą zmienną, dlaczego adres tej zmiennej może się różnić w zależności od różnych wykonań? Proszę zobaczyć mój przykładowy program poniżej:Dlaczego adresy zmiennych lokalnych mogą być różne za każdym razem?

#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; 
} 

Wynik na wykonanie 1:

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

Wynik na wykonanie 2:

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

Wynik na wykonanie 3:

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

Jak widać, otrzymuję różne wyniki przy różnych wykonaniach. Pierwszy wiersz danych wyjściowych odpowiadający adresowi przydzielonej pamięci, który powinien się wydarzyć w stercie - jeśli mają one przypisane różne adresy za każdym razem, ma to dla mnie sens. Jednak nawet kiedy drukuję adresy zmiennych lokalnych - odpowiadające drugiej linii - wyniki są nadal różne.

Na pierwszy rzut oka myślałem, że to dlatego, że program drukuje fizyczny adres pamięci, ale ten wpis, Virtual Memory or Physical Memory, obala moją początkową myśl. Czy jest jakiś powód, że biorąc pod uwagę, że realizacja programów jest "taka sama", bez wątków, żadnych danych wejściowych użytkownika itp., Że nadal istnieją alokacje pamięci z różnymi adresami?

środowisku testowym:

  • Linux 14.04
  • Mac OS X 10,10
+13

Po pierwsze, ASLR prawdopodobnie przyczynia się - czy jest włączony w jądrach w systemach testowych? – fish2000

+2

Tak, to prawie na pewno [ASLR] (https://en.wikipedia.org/wiki/Address_space_layout_randomization) w pracy. –

+1

@ fish2000, z pewnością powinieneś dodać to jako odpowiedź z odrobiną wyjaśnienia. – SergeyA

Odpowiedz

11

Przy przydzielaniu na stercie (przy użyciu operatora new lub malloc() i przyjaciół), program musi poproś system operacyjny o przydzielenie pamięci sterty. Wiele rzeczy zza kulis dzieje się w menedżerze pamięci OS (szczegóły implementacji są w większości wyższe niż moje wynagrodzenie: zbieranie śmieci, konsolidacja odzyskanej pamięci, itp.) I jest to dobra rzecz:, aby nie musieć Pomyśl o tym.

Zmienne lokalne są przydzielane na stosie. Tradycyjnie alokacja stosu byłaby powtarzalna, ale to się zmieniło w ostatnich latach. Address space layout randomization (ASR) to stosunkowo nowa innowacja w zarządzaniu pamięcią systemu operacyjnego, która celowo sprawia, że ​​adresy pamięci w alokacjach stosów (takich jak te, które obserwowałeś) są niedeterministyczne w czasie wykonywania. Jest to funkcja bezpieczeństwa: uniemożliwia to złym aktorom wykorzystywanie przepełnień bufora sterty, ponieważ jeśli implementacja ASLR jest wystarczająco entropijna, kto wie, co będzie na końcu przepełniającego bufora?

Cena, jaką płacisz za tę i inne funkcje zarządzania pamięcią, to kontrola. Zakłady na adresy alokacji na nowoczesnej (niewbudowanej) platformie są jak granie w Powerball: być może zabawnym rozpraszaniem, ale nie wykonalnym planem na przyszłość. Jeśli twój kod działa na platformie AVR-ISA lub jest taki sam, może szanse są na tyle zbliżone do Blackjacka, że ​​ktoś może zostać zachęcony do gry, by wygrać (że tak powiem).

Tak czy inaczej, nie jestem człowiekiem uprawiającym hazard, osobiście - jak często mówię, panowie wolą przydział na stos. Ale to w zasadzie dlaczego uzyskujesz te wyniki.

Dzięki @ T.C. dla linku i @SergeyA dla sugestii.

+4

Nawiasem mówiąc, ASLR dotyczy również lokalizacji stosu, dlatego zmienne lokalne mają również różne adresy przy każdym wykonaniu. O to właśnie chodziło pytanie. –

+0

@JordanMelo dobry punkt - założyłem, że rozumiem takie terminy jak np. "Stos" i "kupa" w odpowiedzi - ale tak, stos programu jest w istocie inicjowany przez menedżera pamięci przy użyciu ASLR i całkowicie chciałem wspomnieć o tym fakcie, dzięki – fish2000

+1

Kiedy mówisz o ASLR jako funkcji bezpieczeństwa, czy oznacza, że ​​chroni przed przepełnieniami bufora stosu (a nie sterty)? Sądzę, że to główna luka, której dotyczy. – Banex