2015-05-25 31 views
4

我知道這是一種危險的行爲,我只是想弄清楚發生了什麼。如果我覆蓋棧上的返回地址,會發生什麼?

守則如下:

#include<stdio.h> 
#include<stdlib.h> 

static int count = 0; 

void hello(void){ 
    count ++; 
    fprintf(stderr,"hello! %d\n",count); 
} 

void foo(void){ 
    void *buf[10]; 
    static int i; 

    for(i = 0 ; i < 100 ; i++){ // put enough data to overwrite the return address on stack 
     buf[i] = hello; 
    } 
} 

int main(void){ 
    int buf[1000]; 
    foo(); 
    return 0; 
} 

而結果:

…… 
hello! 83 
hello! 84 
hello! 85 
hello! 86 
hello! 87 
hello! 88 
hello! 89 
Segmentation fault (core dumped) 

爲什麼你好FUNC被稱爲89時間? 當foo返回時,pc寄存器獲取hello func的地址,不是嗎? 所以你好,叫做,做裏面的事情。那又怎麼樣?程序是不是回到主要功能? 89從哪裏來?我必須誤解一些事情,請指出。

+0

哪個編譯器/操作系統您使用的?另外,你知道buf和buf中的buf沒有任何關係,對吧? – Ashalynd

+0

@Ashalynd centos 7,gcc – MMMMMCCLXXVII

+0

哪個版本的gcc? – Ashalynd

回答

9

你寫的功能hello的地址的堆棧foo超出您保留的空間數量的90倍,數量爲buf。當foo試圖返回,它加載(之一)的hello第一額外地址(ES)到程序計數器,彈出它和「返回」到它。我之所以說「其中之一」是因爲在你保留的數組的末尾和返回地址的開始之間棧中可能有一些空間。

hello假定它是由foo調用。然而,它不叫,換句話說,在中foo剩餘的地址沒有被壓入堆棧hello返回。所以,當hello返回時,它彈出的是堆棧中的下一個東西,它又是hello的地址。

這又看起來像但從hello的函數的調用,但它實際上不是一個電話,因爲它是一個迴歸,所以hello不停地返回到自己和從堆棧每次彈出的hello一個地址,直到它用完這些地址。

那些後跑了出來,在堆棧中的下一個字節,當你作爲一個指針處理還沒有被覆蓋,是在其他地方的記憶,大概是沒有被分配到你的進程的內存映射的東西。 hello試圖回到那個,那就是程序被遺漏的時候。

+0

這就是我想知道的,謝謝 – MMMMMCCLXXVII

5

嗯,這是不確定的行爲。當你進入未分配的內存什麼可能發生取決於目前有什麼「垃圾」。

段錯誤基本上意味着你走出你的程序的受保護內存(在你的情況採取了「89倍」)。您的操作系統爲您辯護,並告訴您,您嘗試在爲該程序分配的空間之外進行編寫。

(這是不是在舊操作系統和這種錯誤的情況下可能會導致操作系統崩潰,如果你的程序溢出到系統空間。)

1

正如那鴻說,這是不確定的行爲,但這並不意味着它不能解釋:

100 - 89 = 11 

的這是,恰恰,你的本地堆棧的大小(無效* [10] + int)。

試試這個(不確定的行爲,可能會刪除你的硬盤或修復全球經濟):

#include<stdio.h> 
#include<stdlib.h> 

static int count = 0; 

static void hello(void){ 
    count ++; 
    fprintf(stderr,"hello! %d\n",count); 
} 

static void foo(void){ 
    void *buf[1]; 
    static int i; 

    for(i = 0 ; i <= 100 + 2; i++){ // put enough data to overwrite the return address on stack 
     buf[i] = hello; 
    } 
} 

static void bye(void) { 
    printf("Bye, bye...\n"); 
    exit(EXIT_SUCCESS); 
} 

int main(void){ 
    void *buf[1000]; 
    int i; 

    for (i = 0; i < 1000; ++i) { 
     buf[i] = &bye; 
    } 
    foo(); 
    return 0; 
} 
相關問題