2012-05-13 30 views
2

首先,當談到C++編程時,我是一名初學者。昨天我遇到了一些相當奇怪的事情。我試圖通過指向它的指針來確定數組的長度。由於sizeof沒有工作,我做了一些谷歌搜索,最終在這個網站上,我發現答案是不可能的。相反,我應該在數組的最後一個索引處放一個超出限制的值,並增加一個計數器,直到達到該索引。因爲我不想覆蓋最後一個索引處包含的信息,所以我試圖在最後一個索引之後放置一個索引超出限制值。我預計它會失敗,但由於某種原因,它沒有。C++:寫入/讀取無效/出界數組索引?

我以爲我犯了一個錯誤別的地方,該陣列是不再那麼我指定以,所以我做了如下試驗:

int a[4]; 
a[20] = 42; 
std::cout << a[20]; 

輸出爲42沒有任何錯誤。爲什麼這個工作?這應該不是有效的,對吧?更有意思的是,它可以處理任何原始類型的數組。但是,一旦我使用std :: string,程序立即存在1.

任何想法?

+0

+1用於調查問題。請參閱C++方面的[未定義行爲](https://en.wikipedia.org/wiki/Undefined_behavior),並學習一些關於實現端的堆棧變量和彙編。 – Pubby

+0

使用'std :: vector '它有一個'size()'成員(或C++ 11中的std :: array)。 –

回答

6

您的系統恰好沒有使用距陣列地址更遠的20 * sizeof(int)字節的內存。 (從它的開始。)或者記憶屬於你的過程,因此你可以混淆它,或者爲自己破壞某些東西,或者只是幸運的巧合破壞一切。

底線,不這樣做:)

+0

感謝您的澄清。這隻能覆蓋由同一進程使用的數據或從字面上存儲在內存中的任何內容? – CaffeineAddict

+0

@Cyber​​punC它依賴於操作系統,但一般規則是:如果它是你的操作系統的數據 - 稱爲進程或任何子進程,你可以做任何你想做的事情。如果它的內存位置在這個瞬間沒有被使用,操作系統通常會讓你向它寫入垃圾,但是它們可以隨後將這個內存分配給另一個進程,之後它們將阻止你訪問它。當然,如果有操作系統本身正在使用的數據,它不會讓你喘口氣。 (從字面上看,它們通常會抓取非常低的內存地址。) – ScarletAmaranth

+0

編譯器將此優化爲std :: cout << 42;',這也是代碼實際執行的操作。 –

0

我認爲你需要了解什麼是以下幾點:
當你創建a[4]編譯器爲4個整數分配內存和a記住的地址第一個:(*a == &(a[0]))。
當你讀\寫編譯器不檢查你是否在邊界(因爲他不再有這個信息)。只需按照以下方式轉到陣列的請求單元的地址:a[X] == &(a + sizeof(int) * X)
在C++中,程序員有責任在訪問數組時檢查邊界。