-1

我尝试实现以下目标:我有一个指向地址的指针p,该地址再次保存一个地址(该地址也是一个有效地址)。现在我想要另一个指向pp地址的指针,它是p. 所以我正在做以下事情:

// Retrieve the start address
unsigned long long *p = getInitialAddress();

// Let pp point to next address
unsigned long long *pp = (unsigned long long*)(*p);

// Print address
printf("0x%llx %p\n", *p, pp);

例如,这将打印:0x7fffedc47a70 0x7fffedc47a70这是所需的结果。

但是,将另一个printf放入代码中,如下所示:

// Retrieve the start address
unsigned long long *p = getInitialAddress();

// Print
printf("%p 0x%llx\n", p, *p);

// Let pp point to next address
unsigned long long *pp = (unsigned long long*)(*p);

// Print address
printf("0x%llx %p\n", *p, pp);

导致:

0x7fffacea3660 0x7fffacea3680
0x0 (nil)

这不是正确的结果,因为它应该是

0x7fffacea3660 0x7fffacea3680
0x7fffacea3680 0x7fffacea3680

那么printf指针中的内容是否有所改变或有什么问题?

编辑:完整代码

unsigned long long* readRBP();

int main(void) {
    // Retrieve the start address
    unsigned long long *p = readRBP();

    // Print
    printf("%p 0x%llx\n", p, *p);

    // Let pp point to next address
    unsigned long long *pp = (unsigned long long*)(*p);

    // Print address
    printf("0x%llx %p\n", *p, pp);

    return 0;
}

unsigned long long* readRBP() {
    unsigned long long rbp;
    __asm__ volatile("mov %%rbp, $0" : "=r"(rbp));
    return (unsigned long long*)rbp;
}

这将获得 rbp(堆栈基指针)。这个指针的内容就是指向下一个rbp的指针,以此类推。这个rbp 来自readRBP()它自己,下一个 rbp 属于,mainmain 之后的下一个是0x0,即最开始。

4

2 回答 2

3

返回的值readRBP是函数的基指针readRBP。然后调用printfwhich 创建自己的堆栈帧。并且该堆栈帧会删除*p.

要看到这是这样,您可以这样编写代码:

int main(void) {
    // Retrieve the start address
    unsigned long long *p = readRBP();
    unsigned long long pContents = *p
    unsigned long long *pp = (unsigned long long*)(*p);

    // Print
    printf("%p 0x%llx %p\n", p, pContents, pp);

    return 0;
}

换句话说,您将所有信息收集到的堆栈框架中main,然后通过调用printf.

于 2012-04-14T15:59:44.863 回答
1
 // Let pp point to next address
  unsigned long long *pp = (unsigned long long*)(*p);

评论是错误的。pp不指向下一个地址,而是指向通过转换p. 我不知道getInitialAddress()应该返回什么,但如果它是调用calloc,或分配一些内存,malloc然后用 清零memset,则很可能指向的内存区域p从零开始。

顺便说一句,您假设long longand void*(即数据指针)具有相同的大小。我不知道它在你的系统上是否正确(例如在 Linux/i686 系统上是错误的)。如果您想要与指针大小相同的整数大小,则更好地使用intptr_t并包含<stdint.h>

要探索你的堆栈,假设最近有一个 GCC 编译器,你可能会对内置的返回地址感兴趣,__builtin_return_address或者__builtin_frame_address

于 2012-04-14T15:19:30.390 回答