查找指针是指向堆栈、堆还是程序文本?

20

有没有方法可以找出指针指向的位置是:

  • 程序(如果是,哪个部分,例如 elf .text)?

此外,这是否可以在可移植的情况下实现(Linux 64/32位,OSX和Windows 7+)?

跟进:

我不是想找出某个东西是否已被 malloc。

我想有效地区分程序中 void* 指向函数和指向栈或堆中数据的 void* 指针。

这是用 C 编写的语言运行时,而不是“普通”的 C 程序。

到目前为止,这个答案是最有用的:Checking if something was malloced


1
请查看此问题的答案:https://dev59.com/h0XRa4cB1Zd3GeqPuLs_。 - user529758
在Windows上,您可以使用WinDbg的!address扩展来为您确定这一点。我不知道*nix操作系统是否也适用。 - user1354557
2个回答

35

由于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

在Intel 32位FreeBSD下使用gcc:

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

在Intel 64位FreeBSD下使用gcc:

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

SPARC-64 FreeBSD下的gcc:

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

运行 MacOS X 的 PowerPC:

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

并且在运行 Linux 的 ARMv6 上:

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

正如你所看到的,可能性是无限的。


1
在Linux下,/proc/self/maps提供了我所需的所有信息。 - fadedbee
2
你是否不小心忘记了创建heap2的代码行? - R Sahu

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

有点粗鲁,除非你在处理指定的平台,否则你不会确切地知道扩展方向或大小。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接