Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
大型2D阵列存在分割错误 我在Linux写了一些C++代码,我声明了一些类似于: double x[5000][500], y[5000][500], z[5000][500];_C++_Linux_Stack Overflow - Fatal编程技术网

大型2D阵列存在分割错误 我在Linux写了一些C++代码,我声明了一些类似于: double x[5000][500], y[5000][500], z[5000][500];

大型2D阵列存在分割错误 我在Linux写了一些C++代码,我声明了一些类似于: double x[5000][500], y[5000][500], z[5000][500];,c++,linux,stack-overflow,C++,Linux,Stack Overflow,编译期间没有错误。当我执行时,它会显示“分段错误” 如果我将数组的大小从5000减少到50,程序运行良好。如何保护自己不受此问题的影响?您的声明应该出现在顶层,不在任何过程或方法中 P>>强>在C或C++代码中诊断StEngult的最简单方法是使用< /St>。如果您的阵列中有一个出现故障,valgrind将准确指出故障的位置和方式。如果错误在别处,它也会告诉你这一点 valgrind可用于任何x86二进制文件,但如果使用gcc-g编译,则会提供更多信息。这些数组位于堆栈上。堆栈的大小非常有限

编译期间没有错误。当我执行时,它会显示“分段错误”


如果我将数组的大小从5000减少到50,程序运行良好。如何保护自己不受此问题的影响?

您的声明应该出现在顶层,不在任何过程或方法中

<> P>>强>在C或C++代码中诊断StEngult<强>的最简单方法是<强>使用< /St>。如果您的阵列中有一个出现故障,valgrind将准确指出故障的位置和方式。如果错误在别处,它也会告诉你这一点


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

编译,则会提供更多信息。这些数组位于堆栈上。堆栈的大小非常有限。你可能会遇到。。。堆栈溢出:)

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

double* x =new double[5000*5000];
但你最好养成使用标准容器的好习惯,这些容器为你包装了所有这些:

std::vector< std::vector<int> > x( std::vector<int>(500), 5000 );
std::vectorx(std::vector(500),5000);

另外:即使堆栈适合阵列,您仍然需要空间让函数在其上放置帧。

在我看来,您的堆栈溢出了

尝试使用gcc的-fstack检查选项编译程序。如果您的阵列太大,无法在堆栈上分配,则会出现StorageError异常


不过,我认为这是一个很好的赌注,因为5000*500*3倍(每个8字节)大约是60兆-没有平台有足够的堆栈。您必须在堆上分配大数组。

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

int main(int, char **) {
   double x[5000][500],y[5000][500],z[5000][500];
   // ...
   return 0;
}
。。。然后,您将溢出堆栈。解决这个问题的最快方法是添加static这个词

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

double x[5000][500],y[5000][500],z[5000][500];
int main(int, char **) {
   // ...
   return 0;
}
解决此问题的第三种最快方法是在堆上分配内存:

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;
}
int main(int,char**){
双精度**x=新双精度*[5000];
双精度**y=新双精度*[5000];
双精度**z=新双精度*[5000];
对于(尺寸i=0;i<5000;i++){
x[i]=新的双精度[500];
y[i]=新的双精度[500];
z[i]=新的双精度[500];
}
// ...
对于(尺寸i=5000;i>0;){
删除[]z[--i];
删除[]y[i];
删除[]x[i];
}
删除[]z;
删除[]y;
删除[]x;
返回0;
}
第四种最快的方法是使用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;
}
#包括
使用std::vector
命名空间{
结构Y:公共向量{Y():向量(500){};
结构XY:公共向量{XY():向量(5000){};
}
int main(int,char**){
XY x,y,z;
// ...
返回0;
}
第五种最快的方法是在堆上分配它们,但要使用模板,这样维度就不会离对象太远:

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;
}
包括
使用名称空间std;
名称空间{
模板
结构Y:公共向量{Y():向量(N){};
模板
结构XY:公共向量{XY():向量(N1){};
}
int main(int,char**){
XY x,y,z;
XY迷你x、迷你y、迷你z;
// ...
返回0;
}
最有效的方法是将二维数组分配为一维数组,然后使用索引算法

以上所有内容都假设您有一些原因,无论是好的原因还是坏的原因,希望创建自己的多维数组机制。如果您没有理由,并且期望再次使用多维数组,则强烈地考虑安装库:

  • 一个很好地使用STL的方法是 使用

  • 一个快速的方法是使用


您可以尝试使用

typedef boost::multi_阵列Double2d;
Double2d x(boost::区段[5000][500]);
double2dy(boost::extenses[5000][500]);
double2dz(boost::extenses[5000][500]);

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

前一个解决方案的另一个解决方案是执行

ulimit -s stack_area

扩展最大堆栈。

关于始终使用向量的一个保留意见:据我所知,如果您离开数组的末尾,它只会分配一个更大的数组并复制所有内容,当您真正使用固定大小的数组时,这些内容可能会产生细微的、难以发现的错误。至少对于一个真正的数组,如果你走到最后,你会出错,这样错误更容易被发现

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {

typedef double (*array5k_t)[5000];

array5k_t array5k = calloc(5000, sizeof(double)*5000);

// should generate segfault error
array5k[5000][5001] = 10;

return 0;
}
#包括
#包括
int main(int argc,字符**argv){
typedef double(*array5k_t)[5000];
阵列5K_t阵列5K=calloc(5000,双尺寸)*5000;
//应生成segfault错误
阵列5K[5000][5001]=10;
返回0;
}

将其置于顶层将导致其使用堆。另一种方法是使用new或malloc(记住在完成时适当地释放内存)。通常,当人们谈论堆时,他们指的是动态分配的。malloc的问题是你失去了2D数组符号…@Norman Ramsey同意,能够写x[i][j]而不是x[i*XDIM]+j对于大多数非痴迷的程序员来说是一个很大的优势。我怀疑OP是物理学家。当我在gcc和g++中使用-fstack_check选项时,它告诉cc1plus:error:unrecogned命令行选项“-fstack_check”尝试-fstack check而不是-fstack_check double m_x[500000][500]、m_y[500000][500]、m_z[500000][500];当我在main()中仅使用statment(如上)执行时,它正在执行。@kar您的优化级别是多少?我相信gcc会将未使用的变量剥离到-O0以上的任何位置。只包含普通旧数据声明的函数应编译为只返回一个值,这意味着它使用MASI
ulimit -s stack_area
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {

typedef double (*array5k_t)[5000];

array5k_t array5k = calloc(5000, sizeof(double)*5000);

// should generate segfault error
array5k[5000][5001] = 10;

return 0;
}