2012-04-14 47 views
-1

我嘗試實現以下操作:我有一個指針p指向一個地址(該地址也是一個有效地址)。現在我想有另一個指針pp指向p的內容地址。所以我做了以下內容:在printf後將變量的內容變量賦值爲NULL

// 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屬於main,下一個主要是0x0,即。即一開始。

+0

您應該在'printf'格式字符串中使用'%p'來打印指針。 – 2012-04-14 15:10:41

+0

但是我正在打印指針的內容,不是嗎? – 2012-04-14 15:12:41

+2

很難相信這真的是你的代碼。如何完成這樣的程序? – 2012-04-14 15:16:16

回答

3

的值readRBP返回值是readRBP函數的基址指針。然後你可以調用printf來創建它自己的堆棧幀。並且該堆棧框架消除了*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前換句話說。

+0

因此,如果我想跟蹤堆棧並將其打印出來,那麼我首先必須收集所有信息,然後將其打印出來。感謝您的解釋,今天吸取了教訓;)再次抱歉刪除。 – 2012-04-14 16:05:14

+0

是的,就是這樣。沒有關於刪除的概念,它只是用完整的代碼來看看'p'的特殊之處。 – 2012-04-14 16:18:54

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

該評論是錯誤的。 pp不指向下一個地址,而是指向由p指向的內存位置的內容獲得的地址。我不知道getInitialAddress()應該返回什麼,但如果它是例如調用calloc,或者分配一些內存與malloc,然後用memset歸零,那麼p指向的內存區很可能以零開始。

順便說一句,你假設long longvoid*(即數據指針)具有相同的大小。我不知道你的系統是否正確(例如,在Linux/i686系統上它是錯誤的)。如果你想在相同尺寸的整體尺寸爲指針更好地利用intptr_t和包括<stdint.h>

探討你的籌碼,假設最近的GCC編譯器,你可能會感興趣的return address builtins特別__builtin_return_address__builtin_frame_address

+0

+1使問題不能被刪除;-)對於整數和指針的奇怪混合,你是完全正確的。但根據問題'* p'是非零的。 – 2012-04-14 15:21:38

+0

我確實想把'p'的內容當作新的指針。原來的'p'來自rbp寄存器。 – 2012-04-14 15:24:35

+0

感謝GCC相關的提示,但我想這樣做「困難的方式」。 – 2012-04-14 15:56:12