2013-05-03 12 views
17

Czy istnieje sposób, aby dowiedzieć się, czy wskaźnik wskazuje na miejscu w:Sprawdź, czy wskaźnik wskazuje na stos, stertę lub tekst programu?

  • stosie
  • sterty
  • lub program (a jeśli tak, to jakie sekcja np elf .text) ?

Czy można to zrobić przenośnie (Linux 64/32 bit, OSX i Windows 7+)?

obserwacji:

Nie próbuję się dowiedzieć, czy coś zostało malloc'd.

Chcę skutecznie odróżnić void * wskaźniki od funkcji w programie od void * pointers do danych na stosie lub stercie.

To jest dla środowiska uruchomieniowego języka napisanego w C, a nie "normalnego" programu C.

Ta odpowiedź jest najbardziej przydatna do tej pory: Checking if something was malloced

+1

Zobacz odpowiedzi na [to pytanie] (http://stackoverflow.com/questions/276612/checking-if-something-was-malloced). –

+0

W systemie Windows możesz użyć rozszerzenia '! Address' programu WinDbg, aby to ustalić. Nie wiem o * systemach operacyjnych opartych na nix. – user1354557

Odpowiedz

31

Nie możesz robić, co chcesz w przenośny sposób, ponieważ standard języka C nie określa stos, część programu, a sterty jako odrębne obszary. Ich lokalizacja może zależeć od architektury procesora, systemu operacyjnego, modułu ładującego, łącznika i kompilatora. Próbowanie odgadnąć, gdzie wskazuje wskaźnik, przerywa abstrakcję dostarczoną przez C, więc prawdopodobnie nie powinieneś tego robić.

Istnieją jednak sposoby na napisanie kodu, który będzie słusznym odgadywaniem dla określonego środowiska. Robisz to, badając adresy istniejących obiektów i szukając wzorów. Rozważ następujący program.

#include <stdlib.h> 
#include <stdio.h> 

void 
function() 
{ 
    int stack2; 

    printf("stack2: %15p\n", &stack2); 
} 

int 
main(int argc, char *argv[]) 
{ 
    int stack; 
    void *heap = malloc(1); 
    void *heap2 = malloc(1); 

    printf("program: %15p\n", main); 
    printf("heap: %15p\n", heap); 
    printf("heap2: %15p\n", heap2); 
    printf("stack: %15p\n", &stack); 
    function(); 
    return 0; 
} 

Badając jego wydruki, możesz zobaczyć wzorzec, taki jak na przykładzie systemu x64 Linux.

program:  0x400504 
heap:   0x1675010 
heap2:   0x1675030 
stack: 0x7fff282c783c 
stack2: 0x7fff6ae37afc 

Z powyższego można stwierdzić, że (prawdopodobnie) sterta rośnie w górę z 0x1675010, cokolwiek pod nim jest kod programu (lub dane statyczne, które nie wspominając), i że stos rośnie w sposób sposób nieprzewidywalny (prawdopodobnie z powodu losowania stosu) wokół bardzo dużego adresu, takiego jak 0x7fff282c783c.

Porównaj to z mocy cieplnej przy 32-bitowym Intel Linux:

program:  0x804842f 
heap:   0x804b008 
heap2:   0x804b018 
stack:  0xbf84ad38 
stack2:  0xbf84ad14 

Microsoft Windows i 32-bitowego Microsoft kompilator C:

program:  01271020 
heap:   002E3B00 
heap2:   002E3B10 
stack:   0024F978 
stack2:   0024F964 

gcc pod Windows Cygwin:

program:  0040130B 
heap:   00A41728 
heap2:   00A417A8 
stack:   0028FF44 
stack2:   0028FF14 

gcc pod Intel 32-bitowy FreeBSD:

program:  0x8048524 
heap:   0x804b030 
heap2:   0x804b040 
stack:  0xbfbffb3c 
stack2:  0xbfbffb1c 

gcc pod Intel 64-bitowym FreeBSD:

program:  0x400770 
heap:  0x801006058 
heap2:  0x801006060 
stack: 0x7fffffffdaec 
stack2: 0x7fffffffdabc 

gcc pod SPARC-64 FreeBSD:

program:  0x100860 
heap:   0x40c04098 
heap2:  0x40c040a0 
stack:  0x7fdffffe9ac 
stack2: 0x7fdffffe8dc 

PowerPC z systemem MacOS X:

program:   0x1ed4 
heap:   0x100120 
heap2:   0x100130 
stack:  0xbffffba0 
stack2:  0xbffffb38 

PowerPC z systemem Linux:

program:  0x10000514 
heap:   0x100c6008 
heap2:  0x100c6018 
stack:  0xbff45db0 
stack2:  0xbff45d88 

StrongARM działa NetBSD:

program:   0x1c5c 
heap:    0x5030 
heap2:   0x5040 
stack:  0xefbfdcd0 
stack2:  0xefbfdcb4 

i ARMv6 systemem Linux:

program:   0x842c 
heap:   0xb63008 
heap2:   0xb63018 
stack:  0xbe83eac4 
stack2:  0xbe83eaac 

Jak widać możliwości są nieograniczone.

+2

+1. Bardzo pouczająca demonstracja. –

+0

Pod Linuksem,/proc/self/maps dostarcza mi wszystkich potrzebnych informacji. – fadedbee

+2

Czy w jakiś sposób zapomniałeś linii kodu do tworzenia 'heap2'? –

0

można określić położenie generalnie stosu i sterty, choć, jak duże jest to będzie zupełnie inna historia ...

void *heap_locations; 
void *stack_location; 

void determine_locations (int any_int) { 
    free(heap_location = malloc(248)); 
    stack_location = &any_int; 
} 

int main(int argc, char *argv[]) { 
    determine_locations(argc); 
     . 
     . 
     . 
    return 0; 
} 

Trochę niegrzeczny i nie będzie znać kierunek ekspansji lub rozmiar albo dla absolutnej pewności, chyba że masz do czynienia z określonymi platformami.

Powiązane problemy