-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 の後の次の rbp は0x0です。つまり、まさに最初です。

4

2 に答える 2

3

返される値readRBPは、関数のベース ポインターですreadRBPprintf次に、独自のスタック フレームを作成するを呼び出します。そして、そのスタック フレームは のデータを消去し*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 に答える