2014-10-08 21 views
1

我們今天在我的數據結構類中討論了不同的編譯器行爲。下面的例子(加上我的一些cout'ing和其他修補)作爲一個程序,可以在g ++上編譯,但不一定在所有其他編譯器上。C++(g ++編譯器)動態初始化靜態聲明的數組導致內存問題

#include <iostream> 

using namespace std; 

int main(void) 
{ 
    int i; 
    int j = 5; 

    cout << "i address: " << &i << " -- j address: " << &j 
     << endl << "enter size: "; 
    cin >> i; 
    cout << "value i: "<< i << "; size memory of i (ints): "<<(&i - &j)<< endl; 

    int a[i]; 

    cout << "address of array a start: " << a << endl; 

    int b = 14; 

    cout << "value b: " << b << "; b address= " << &b << endl 
     << "distance bt j and b(ints): "<< (&j - &b) << endl; 
    cout << "distance bt b and start of array(ints): " << (&b - a) << endl; 
} 

玩弄輸入(和學習一些關於如何動態數組在過程中分配的內存)後,我決定進入0是最有趣的。輸出:

i address: 0x7fff5b303764 -- j address: 0x7fff5b303760 
enter size: 0 
value i: 0; size memory of i (ints): 1 
address of array a start: 0x7fff5b3036b0 
value b: 14; b address= 0x7fff5b303754 
distance bt j and b(ints): 3 
distance bt b and start of array(ints): 41 

我的問題:

  1. 如何G ++知道治療陣列作爲一個需要被動態創建VS立即試圖靜態地創建一個與任何的默認值我是或拋出某種編譯時錯誤?

  2. j和b之間的距離是3int的內存而不是預期的1.這是怎麼回事?我懷疑,純粹是通過玩弄該計劃收集的經驗證據,它與該cout有關,但我不熟悉如何/爲什麼他們會以似乎隨機的數量存儲在內存中。

  3. 我爲數組a的大小輸入了0,並且基於以不同大小玩耍,我認爲長度爲0的動態數組不可能被初始化爲長度爲41.因此,如果它不是數組佔用所有這41個內存值,然後存儲在b(堆棧中存儲的最後一個數據)和數組a(第一個數據有目的地存儲在堆中)之間的內容是什麼,爲什麼它存在於那裏?

+0

所有這些指針減法都會導致未定義的行爲。爲了理解g ++在做什麼,研究這個程序產生的彙編代碼可能是有益的。 – 2014-10-08 03:41:57

+0

[鏈接到未優化的程序集](http://goo.gl/in9nEY) – 2014-10-08 03:49:56

+0

@MattMcNabb我從來沒有使用過彙編語言。但很高興知道我可以用它作爲資源,更深入地研究將來在這些情況下會發生什麼。當我對這個話題感覺足夠舒適時,肯定會回顧你提供的鏈接,因爲對於這裏究竟發生了什麼仍然存在一些含糊不清的問題。感謝您在回答我的問題時所付出的時間和精力。乾杯。 – jvanstry 2014-10-08 04:15:14

回答

2

a是一個可變長度排列構成的非標準C++但克++擴展的一部分。 g ++知道它不是編譯時確定大小的常規數組,因爲i不是編譯時常量,例如const int i = 3;a不存儲在堆上。它存儲在堆棧中。我想jb之間的地址距離取決於分配給a的大小,只能在運行時才知道。我不知道如何計算大小爲0的ba之間的距離。如果您構建在調試模式下,則可能會在陣列後添加一些額外的隱藏緩衝區,以便檢測超出範圍的意外覆蓋陣列。

+0

根據你所說的,分配給a的內存在堆棧上,也在運行時分配?在這種情況下,j和b之間怎麼樣?他們在記憶中的相對位置是這樣的(以ints表示的距離)i-1> j-> b-41-> a。如果a在b之後不在它們之間,j和b之間的距離如何計算?它在某些時候會移動嗎? – jvanstry 2014-10-08 02:42:49

+0

@jvanstry我沒有仔細考慮確切的數字。如果需要,編譯器可以對堆棧中的這些變量進行重新排序。有時對於'x-y',你先把變量放在第一位,有時候先放變量。我不知道這將如何影響計算。 – 2014-10-08 02:45:06

+0

編譯器可以根據需要在堆棧上安排變量。最有可能的是,它將所有可變長度的東西放在所有固定大小的東西之上,以便所有固定大小的變量都處於不依賴於數組大小的恆定位置。 – Wyzard 2014-10-08 02:45:22