2013-05-03 127 views
17

是否有以找出是否一個指針在的位置處指向的方式:找出指針是指向堆棧,堆或程序文本嗎?

  • 堆棧
  • 或程序(並且如果是這樣,這部分例如小精靈的.text) ?

此外,這可以做到可移植(Linux 64/32位,OSX和Windows 7 +)?

跟進:

我不會試圖找出是否有什麼東西被malloc分配。

我想有效地區分void *指針和程序中的函數void *指向堆棧或堆上的數據。

這是用C編寫的語言運行庫,而不是「普通的」C程序。

這個答案一直是最有用至今:Checking if something was malloced

+1

請參閱[這個問題]的答案(http://stackoverflow.com/questions/276612/checking-if-something-was-malloced)。 – 2013-05-03 14:02:49

+0

在Windows上,您可以使用WinDbg的「!address」擴展名爲您確定。我不知道基於nix的操作系統。 – user1354557 2013-05-03 14:24:24

回答

31

你不能做你的便攜式方式想要什麼,因爲C語言標準沒有規定的堆棧,程序區和堆爲不同的領域。它們的位置可以取決於處理器體系結構,操作系統,加載程序,鏈接程序和編譯器。試圖猜測指針指向的位置是否違反了C提供的抽象,所以你可能不應該這樣做。

儘管如此,仍然有許多方法可以編寫能夠針對特定環境進行正確猜測的代碼。您可以通過檢查現有對象的地址並查找模式來做到這一點。考慮下面的程序。

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

通過檢查其輸出,您可以看到一個模式,例如x64 Linux上的以下模式。

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

從上面可以確定(可能)堆從0x1675010向上生長,它下面什麼是程序代碼(或靜態數據,這些數據並沒有提及),並且紙疊生長在一個不可預知的方式(可能是由於堆棧隨機化)圍繞一個非常大的地址,如0x7fff282c783c。

比較這與在32位Intel的Linux輸出:

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

Microsoft Windows和32位Microsoft C編譯器:

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

在Windows Cygwin的GCC:

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

英特爾32位FreeBSD下的gcc:

0123在Intel 64位的FreeBSD
program:  0x8048524 
heap:   0x804b030 
heap2:   0x804b040 
stack:  0xbfbffb3c 
stack2:  0xbfbffb1c 

GCC:

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

GCC下SPARC-64的FreeBSD:

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

的PowerPC運行的MacOS X:

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

的PowerPC運行Linux:

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

的StrongARM運行的NetBSD:

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

和ARMv6的運行Linux:

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

正如你所看到的可能性是無窮無盡的。

+2

+1。非常翔實的示範。 – 2013-05-03 14:43:29

+0

在Linux下,/ proc/self/maps爲我提供了所有我需要的信息。 – fadedbee 2013-05-07 07:32:58

+2

你有沒有忘記創建'heap2'的代碼行? – 2015-01-19 19:54:56

0

可以大致判斷棧和堆的來講,雖然它是多麼大的將是另一個故事的位置...

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

有點粗魯,你不會知道的擴張方向或大小要麼絕對確定,除非你正在處理指定的平臺。