2015-09-16 54 views
-4

我以爲我喜歡從C++ 11中獲得std :: array的想法,但它看起來像有一些夸克。我發現了這一點,因爲下面的代碼給出了一個段故障:2維std :: array woes

#include<array> 
#include<iostream> 

int main() { 
     std::array<std::array<int*, 5>, 4> sum; 

     //Initialize sum array 
     std::cout << sum.size() << " " << sum[0].size() << "\n"; 
     for (size_t i = 0; i < sum.size(); i++) { 
       for (size_t j = 0; j < sum[0].size(); j++) { 
         if (i == 0 || j == 0) 
           *(sum[i][j]) = 0; 
         else 
           sum[i][j] = nullptr; 
       } 
     } 

    return 0; 
} 

此輸出:

4 5 
Segmentation fault (core dumped) 

sum.size()返回4,如所預期,並返回sum[0].size()5,如所預期; IE看起來好像我們有一個4行5列的數組。但是,當我嘗試執行此程序時(如上所示),我遇到了分段錯誤。 This link建議顛倒我訪問我的數組的方式(如更改sum[i][j]sum[j][i])的順序應該可行,但我也會遇到seg-fault。這使我覺得我可能已經做錯事與我的指針(我有點生疏我的C++),所以我改變總和是整數數組,所以它的內容如下:

#include<array> 
#include<iostream> 

int main() { 
     std::array<std::array<int, 5>, 4> sum; 

     //Initialize sum array 
     std::cout << sum.size() << " " << sum[0].size() << "\n"; 
     for (size_t i = 0; i < sum.size(); i++) { 
       for (size_t j = 0; j < sum[0].size(); j++) { 
         if (i == 0 || j == 0) 
           sum[i][j] = 0; //works as sum[j][i] too!!! 
         else 
           sum[i][j] = 1; 

     std::cout << sum[i][j]; 
       } 
    std::cout << "\n"; 
     } 

     std::cout << "here\n"; 
    return 0; 
} 

其中一期工程,並輸出:

4 5 
00000 
01111 
01111 
01111 
here 

不過,我很困惑,因爲如果我切換sum[i][j]年代到sum[j][i]的,它也可以輸出同樣的事情!當我在第一次運行內循環的最後一次迭代期間嘗試sum[5][0]時,我期望得到seg-fault!我現在願意稱自己爲hela困惑。到底是怎麼回事?

其他信息:我正在使用g ++ 4.8.4和-std = C++ 11標誌集。

+4

您在第一個片段中有未初始化的'int *'... – Jarod42

+1

您不應該取消引用未初始化的指針。在第二個片段中,它不是'int *' – Gombat

+1

出界訪問是UB,並且*「working」*是有效的UB。 – Jarod42

回答

2

第一個代碼段不起作用,因爲您正在訪問隨機存儲器位置。你(基本上)聲明瞭一個(未初始化的)指針的二維數組,並且在你的代碼中你將它們解引用,這是未定義的行爲,並且很可能導致段錯誤(你試圖在隨機存儲器位置寫入,這很可能是非映射在當前虛擬地址空間中)。

第二段代碼很好;反轉這兩個索引是錯誤的,但是你沒有得到任何錯誤,因爲std::array(或者由底層C數組上的編譯器)沒有執行明確的限制檢查。當遇到無效索引(第一個索引爲4)時,會發生什麼情況在技術上仍然是未定義的行爲;在實踐中,您可能會覆蓋堆棧中無關的變量,並且該程序會一直保持運行。

+0

我的指針生鏽了!感謝您解釋 – Sammaron

1
// This is undefined behavior too 
int* array[4][5]; 
*(array[0][0]) = 0; 

// This is also undefined behavior, and for the same reason 
int *cell; 
*cell = 0; 

如果你想使用指針指向的對象,你必須使它指向一個實際的對象;例如通過分配一個有效對象的地址給它,或者創建一個全新的對象(例如new)並將其分配給指針。

不知道你的最終目標,使用指針看起來像一個非常奇怪的設計選擇;切換到數組int可能是對的。

+0

謝謝,這有幫助。爲了記錄,我使用了int指針,因爲你不知道一個普通的整數是否是未初始化的,我想我可以避免使用一個包裝類來利用'nullptr'來標識未初始化的指針。 – Sammaron