大型2D阵列给出了分段故障

23 c++ linux stack-overflow

我正在Linux中编写一些C++代码,我已经声明了一些2D数组,如下所示:

 double x[5000][500], y[5000][500], z[5000][500];
Run Code Online (Sandbox Code Playgroud)

在编译期间没有错误.当我执行它时说"分段错误".

Wen我将数组的大小从5000减少到50,程序运行正常.我该如何保护自己免受这个问题的影响?

Tho*_*day 64

如果您的程序看起来像这样......

int main(int, char **) {
   double x[5000][500],y[5000][500],z[5000][500];
   // ...
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

...然后你堆满了.解决此问题的最快方法是添加单词static.

int main(int, char **) {
   static double x[5000][500],y[5000][500],z[5000][500];
   // ...
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

解决此问题的第二种最快方法是将声明移出函数:

double x[5000][500],y[5000][500],z[5000][500];
int main(int, char **) {
   // ...
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

修复此问题的第三种最快方法是在堆上分配内存:

int main(int, char **) {
   double **x = new double*[5000];
   double **y = new double*[5000];
   double **z = new double*[5000];
   for (size_t i = 0; i < 5000; i++) {
      x[i] = new double[500];
      y[i] = new double[500];
      z[i] = new double[500];
   }
   // ...
   for (size_t i = 5000; i > 0; ) {
      delete[] z[--i];
      delete[] y[i];
      delete[] x[i];
   }
   delete[] z;
   delete[] y;
   delete[] x;

   return 0;
}
Run Code Online (Sandbox Code Playgroud)

第四种最快的方法是使用std :: vector在堆上分配它们.文件中的行数较少,但编译单元中的行数较多,您必须为派生的矢量类型考虑一个有意义的名称,或者将它们塞进一个匿名的名称空间中,这样它们就不会污染全局名称空间:

#include <vector>
using std::vector
namespace { 
  struct Y : public vector<double> { Y() : vector<double>(500) {} };
  struct XY : public vector<Y> { XY() : vector<Y>(5000) {} } ;
}
int main(int, char **) {
  XY x, y, z;
  // ...
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

第五种最快的方法是在堆上分配它们,但是使用模板使得维度不是远离对象:

include <vector>
using namespace std;
namespace {
  template <size_t N>
  struct Y : public vector<double> { Y() : vector<double>(N) {} };
  template <size_t N1, size_t N2>
  struct XY : public vector< Y<N2> > { XY() : vector< Y<N2> > (N1) {} } ;
}
int main(int, char **) {
  XY<5000,500> x, y, z;
  XY<500,50> mini_x, mini_y, mini_z;
  // ...
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

最高效的方法是将二维数组分配为一维数组,然后使用索引算法.

所有上述假设你有一些理由,一个好的或一个好的,因为想要制作你自己的多维数组机制.如果您没有理由,并希望再次使用多维数组,请强烈考虑安装库:


xto*_*ofl 16

这些数组在堆栈中.堆栈的大小非常有限.你可能遇到...堆栈溢出:)

如果你想避免这种情况,你需要将它们放在免费商店:

double* x =new double[5000*5000];
Run Code Online (Sandbox Code Playgroud)

但是你最好开始使用标准容器的好习惯,它为你包装所有这些:

std::vector< std::vector<int> > x( std::vector<int>(500), 5000 );
Run Code Online (Sandbox Code Playgroud)

另外:即使堆栈适合阵列,您仍然需要空间来放置框架.


Ben*_*oît 5

您可能想尝试使用Boost.Multi_array

typedef boost::multi_array<double, 2> Double2d;
Double2d x(boost::extents[5000][500]);
Double2d y(boost::extents[5000][500]);
Double2d z(boost::extents[5000][500]);
Run Code Online (Sandbox Code Playgroud)

实际的大内存块将在堆上分配,并在必要时自动释放.


Nor*_*sey 4

您的声明应出现在顶层,位于任何程序或方法之外。

到目前为止,诊断C 或 C++ 代码中的段错误的最简单方法是使用valgrind。如果您的某个阵列出现故障,valgrind 将准确指出故障位置和故障方式。如果故障出在其他地方,它也会告诉你。

valgrind 可用于任何 x86 二进制文件,但如果使用gcc -g.

  • Toplevel 使其成为全局的(未初始化的数据,永远不会恢复)。通常,当人们谈论堆时,他们指的是动态分配。malloc 的问题是你丢失了二维数组符号...... (2认同)