2014-07-23 91 views
2

我已經讀了有點類似的問題(why this code works in C),但它實際上並沒有得到解釋,爲什麼是這一段代碼實際工作:爲什麼此代碼實際工作?

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

typedef struct example 
{ 
    char length[2]; 
} STRUCT; 

int main (void) 
{ 
    STRUCT test; 
    strcpy(test.length, "********"); 
    puts(test.length); 
    return 0; 
} 

我使用的代碼塊編譯它,所以我猜測它是在我的字符串中分配更多空間來默認存儲額外的星號......我真的不知道。也許我很幸運,但每次運行它都可以。

在上面的示例(鏈接)中,他將2個元素放在2的數組中,這裏我使用的空間比字符串可以處理的要多得多,或者可以。

+1

HTTP://en.wikipedia。org/wiki/Buffer_overflow,是的,你很幸運。在你分配的界限之外寫入的內容是未定義的行爲,並且可能導致從絕對沒有一直到崩潰操作系統的任何問題(或者可能更糟) –

+4

程序展示[*未定義的行爲*](http:// en.wikipedia.org/wiki/Undefined_behavior)並且不合格。這只是運氣,它運行,運氣和[鼻惡魔](http://www.catb.org/jargon/html/N/nasal-demons.html)。 –

+1

歡迎來到未定義行爲的世界。這是最糟糕的一種未定義的行爲 - 代碼起作用。它將工作多年,直到真正令人討厭的事情發生。有時會以CNN或slashdot結尾 – pm100

回答

1

你真幸運。

該結構只聲明爲兩個字節長,但編譯器或運行時間可能會分配更多或只是不關心內存位置struct - 事實是,strcpy將覆蓋內存後struct,如果在更大的上下文中使用,它最終會覆蓋某些對其他內容至關重要的內存,並且會根據所覆蓋的內存類型以及使用的內存類型創建一個災難性錯誤。

在你的情況下,程序只是退出,所以機會(幸運的是)沒有人會使用你已經損壞的內存。

3

C不檢查數組邊界。它會導致緩衝區溢出和未定義的行爲,如Ricky Mutschlechner在評論中所述。

+0

是的,我知道,我只是認爲編譯器可以幫助解決這種情況。 –

+0

@matt_s - 不,它不。 – Soren

0

它的工作原理是因爲寫入(但未分配)的內存未被此應用程序的其他部分使用。我不知道內存分配是如何工作的以及大塊的細節。 只需搜索更多細節。

它不會使操作系統崩潰,但會在最壞的情況下導致分段錯誤。

+0

從技術上講,因爲它是UB,所以*可能會使操作系統崩潰。 –

+0

取決於操作系統。老,小,嵌入式 - 他們會崩潰 – pm100

+1

我同意,取決於操作系統。 http://stackoverflow.com/questions/15646973/how-dangerous-is-it-to-access-an-array-out-of-bounds – nvd

1

這是未定義行爲的示例(正如人們在評論中提到的那樣)。

至於爲什麼特別是這個工作,它很可能是由於堆棧對齊。因此,當您聲明STRUCT test時,即使它只需要堆棧中的兩個字節,編譯器也會將堆棧向下對齊(通過爲結構添加額外的填充),因此在test之後得到了額外的未使用空間,其中strcpy寫入。因爲程序中沒有其他部分使用這個空間,所以它給人一種沒有問題的幻覺。

0

它只是溢出你的堆棧,因爲測試是堆棧。 現在可能沒有任何問題,但是如果你在棧上聲明瞭一些更多的變量以及測試,那可能會導致一些問題

+0

堆棧溢出是一種不同類型的錯誤。您可能想說「它正在**進入**堆棧」。 –

0

您正在寫入位於test.length之後的堆棧內存中。爲了說明這個問題好,我加了兩行代碼:

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

typedef struct example 
{ 
    char length[2]; 
} STRUCT; 

int main (void) 
{ 
    STRUCT test; 
    unsigned int foo = 42; 
    strcpy(test.length, "********"); 
    puts(test.length); 
    printf("%u", foo); 
    return 0; 
} 

您期望中的printf打印42,但是變量foo得到由strcpy的覆蓋。真正的輸出,例如在海灣合作委員會,在(你可以測試它here)以下:

******** 
707406378 
相關問題