2015-09-16 32 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