【问题标题】:C Program crashing with large arraysC 程序因大数组而崩溃
【发布时间】:2014-07-17 11:51:01
【问题描述】:

我正在尝试运行一个涉及大量计算和值的模拟。

我遇到了一个问题,即大型数组会导致程序在声明任何变量之前崩溃。我不确定这是由于我的代码还是由于我的操作系统拒绝运行程序。

导致程序崩溃的代码是:

long double adsorption[2][4][5][10001]

这个数组应该使用大约 10^6 字节,而 SIZE_MAX 是 10^19,所以我很困惑它为什么会崩溃。 (任务管理器中的程序是 64 位的)

我在具有 12 Gb 内存的 Windows 7 64 位上运行,其中 10 Gb 通常是免费的。编译器是 MinGW-w64

抱歉,如果这是非常基本的,我来自物理背景,不是编码!

干杯

【问题讨论】:

  • 堆栈(大多数编译器在其上放置局部变量)通常有一个位数的可用兆字节数。例如,在 Windows 上,它通常是一个单兆字节,而如果 long double 是 80 位,那么您的数组等至少是 400 万字节(几乎 4 MB),如果 long double 是 128 位,则远远超过 6 MB .
  • 如果你把它声明为一个局部变量,那么它通常会被分配到栈上,栈的大小是有限的,所以你会得到一个栈溢出
  • 你能解释一下为什么你有这么多维度的数组,也许我们可以提供一个更好的选择。当前答案提到malloc,但很可能 2 x 4 x 5 x 10001 数组不是最好的方法。还有long double?我认为从来没有需要

标签: c arrays gcc


【解决方案1】:

adsorption 正在堆栈上分配,它必须溢出堆栈。因此错误。

使用malloc 和family 在heap 上分配大块数据。

编辑

或者让它成为静态的——@Matt McNabb 谢谢! :-)

【讨论】:

    【解决方案2】:

    这是堆栈溢出。

    牢记这一点;

    1 byte =    n bits
    1 kb   = 1024 bytes = 2^10 bytes
    1 mb   = 1024 kb    = 2^20 bytes
    1 gb   = 1024 mb    = 2^30 bytes
    1 tb   = 1024 gb    = 2^40 bytes
    

    假设 gcc 中的默认堆栈大小为(根据this webpage);

    • Linux1.8MB | 1,872KB | 1,916,928 bytes

    • Windows1MB | 1,024KB | 1,048,576 bytes


    扩展 rohit 的答案(最初我只是想写评论,但写评论的内容太多了,我最后有一个解决方案),如果你的数组有3,200,320 bytes | 3,125KB | 3MB

    每个平台上堆栈溢出的大小是;

    • Linux3,125KB - 1,872KB = 1,253KB | 1,283,072 bytes 溢出。

    • Windows3,125KB - 1,024KB = 2,101KB | 2,151,424 bytes 溢出。


    要让 gcc 用更大的堆栈编译你的程序,比如 8MB,你可以这样做;

    gcc file.c -Wl,--stack,8388608
    

    并且程序不应该溢出,因为在将数组放入堆栈后,您会留下:

    • 8,388,608 - 3,200,320 = 5,188,288 bytes | 5,066KB | 4.9MB 的堆栈空间。

    【讨论】:

      【解决方案3】:

      2*4*5*10001 = 400,040 个元素。 双精度表示每个元素 8 个字节。 而 400,040 * 8 = 3,200,320 字节

      3,200,320 字节大小超出了要处理的堆栈内存大小。

      【讨论】:

        【解决方案4】:

        局部变量隐含地具有自动存储持续时间,因此它们被有效地放置在空间有限的堆栈中。要么用 static 限定符声明你的数组,将它移到全局范围内,在任何函数之外(所以现在它隐含 静态存储持续时间,哪些变量放在数据段上,请注意 static 在此context 意味着完全不同的东西,所以不要在那里“显式”),或者使用 <stdlib.h> 标头中的 malloccalloc 函数在堆上分配它(如果数组索引的大小已知运行,则特别有用-时间)。

        请注意,C99 还具有可变长度数组 (VLA),其中索引的大小由运行时确定,但仅限于自动存储持续时间。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-31
          • 1970-01-01
          • 2023-03-14
          • 2019-12-26
          相关资源
          最近更新 更多