【问题标题】:Segmentation fault: 11 with large array [duplicate]分段错误:11个大数组[重复]
【发布时间】:2016-03-29 13:06:21
【问题描述】:

一个简单的程序编译良好,但运行时出错:segmentation fault: 11

int length=10000;
int num=100;
int num1=20;
int datablocklen=400002; //datablocklen=2*num1*length+2

int main(){
  double arr[num*length];
  double res[num][num];
  for(int i=0;i<num;i++){
    for(int j=0;j<num;j++){
      res[i][j]=0;
    }
  }
  for(int i=0;i<(num*length);i++){
    arr[i]=i;
  }
  int ntile=(int)(num/num1);
  double array_task[datablocklen];
  for(int i=0;i<ntile;i++){
    for(int j=0;j<ntile;j++){
    array_task[datablocklen-2]=i*num1*length;
    array_task[datablocklen-1]=j*num1*length;
      for(int k=0;k<(num1*length);k++){
        array_task[k]=arr[i*num1*length+k];
        array_task[num1*length+k]=arr[j*num1*length];
      }
    }
  }
return 0;
}

gcc -o test -std=c99 test.c 获取可执行文件。

还是很奇怪,如果长度被分配一个小的值,比如1000,错误不会出现。但是当它大于10000时,就会发生分段错误。

注意,我始终关注 datablocklen 的值,以确保 datablocklen=2*num1*length+2。所以如果lengthnum1 改变,我也会改变变量datablocklen

我在 mac、OS yosemite 下处理 gdb 时仍有一些问题。所以我没有用gdb调试过程序。但是,如果我注释了内部 for 循环,即由 k 索引的循环,程序执行得很好。我的意思是,没有错误消息。

【问题讨论】:

  • 计算机可能很强大,但也有局限性。你不能只投入大量的数字并期望一切顺利进行。如果您确实需要使用大量数字,请尝试使用 Ruby 或 Python 3。
  • @SouravGhosh 我不确定。我看到页面说这种错误可能是由于内存或交换限制,或者 stackoverflow 的事情。我不知道。
  • 是堆栈溢出,将-fsanitize=address添加到gcc中,再次运行。另外,我用 gcc 优化 -O2 对其进行了测试,它没有 segv ... gdb 跟踪在这里 pastebin.com/SyXWdrpt
  • @Lundin 很好的解释。

标签: c


【解决方案1】:

我认为这里的堆栈内存是这里的问题。

两种解决方案:

  1. 为您的进程增加堆栈大小。 通常ulimit -s会显示linux、mac中任何进程的默认大小

  2. 不要在堆栈中分配如此大的数组double arr[num*length];使用malloc在堆中分配这样的内存。

【讨论】:

  • 通常它只是将大型数组移到 main 之外,从而将它们从堆栈中移出。
  • @ThomasPadron-McCarthy 是的,好点。全局数组将存储在数据段中,直到进程终止。使用 malloc 时,您可以控制该内存,并且可以随时释放。
【解决方案2】:

您可能正在溢出堆栈。它的默认值通常约为 8MB。由于您的分配大小是固定的,您可以将大数组移动到全局空间并将许多固定值切换到定义。这是一个例子[请原谅无偿的风格清理]:

#define LENGTH          10000
#define NUM             100
#define NUM1            20
#define NTILE           (NUM / NUM1)

#if 0
#define DATABLOCKLEN    400002              // DATABLOCKLEN=2*NUM1*LENGTH+2
#else
#define DATABLOCKLEN    (2 * NUM1 * LENGTH + 2)
#endif

double arr[NUM * LENGTH];
double res[NUM][NUM];
double array_task[DATABLOCKLEN];

int
main()
{

    for (int i = 0; i < NUM; i++) {
        for (int j = 0; j < NUM; j++) {
            res[i][j] = 0;
        }
    }

    for (int i = 0; i < (NUM * LENGTH); i++) {
        arr[i] = i;
    }

    for (int i = 0; i < NTILE; i++) {
        for (int j = 0; j < NTILE; j++) {
            array_task[DATABLOCKLEN - 2] = i * NUM1 * LENGTH;
            array_task[DATABLOCKLEN - 1] = j * NUM1 * LENGTH;
            for (int k = 0; k < (NUM1 * LENGTH); k++) {
                array_task[k] = arr[i * NUM1 * LENGTH + k];
                array_task[NUM1 * LENGTH + k] = arr[j * NUM1 * LENGTH];
            }
        }
    }

    return 0;
}

【讨论】:

  • 不客气。仅供参考,我刚刚调整了您的数组大小,它们总计为 11.2 MB
猜你喜欢
  • 2018-10-30
  • 1970-01-01
  • 2015-07-14
  • 2019-03-24
  • 1970-01-01
  • 2013-02-17
  • 2016-03-13
  • 1970-01-01
相关资源
最近更新 更多