【问题标题】:C maximum size in main [duplicate]C主文件中的最大大小[重复]
【发布时间】:2011-03-16 09:40:01
【问题描述】:

可能重复:
C programming, why does this large array declaration produce a segmentation fault?

这是我第一次来这里,如果我违反了一些规则或者之前已经回答过这个问题,非常抱歉。 我最近做了一个 C 程序,其中有一个矩阵

char buff[NR][1024*1024];

我需要 NR = 128。所以程序将分配 128MB。这是在 main() 中。我在几个内存足够的系统上尝试过,编译时没有错误。在运行时,我在所有系统上都收到了分段错误。它适用于 NR = 7,但不适用于 8。 我将该代码移到 main 之外,使其成为全球性的。即使是128,它也不再崩溃。 有谁知道为什么会这样? 编译器是 GCC

【问题讨论】:

标签: c memory


【解决方案1】:

问题是您正在溢出通常只有几 MB 大小的堆栈(确切大小取决于系统和您的编译器选项)。您可以使用malloc 在堆上分配内存。

【讨论】:

  • 如果他使用 C,他可能应该使用 malloc。
  • OP 可以告诉编译器也使用更大的堆栈 (stackoverflow.com/questions/156510/…) .. 但基本上你是对的 :)
  • @SB:是的,对不起!现在修好了。 @akira:我不建议将堆栈大小增加到 128MB。
  • @JAB,是的,全局变量非常糟糕。我想说#1 最佳实践规则是永远不要对任何事情使用全局变量。 (全局 const 表当然可以。)如果您需要一个太大而无法在堆栈上可靠分配的对象,请使用 malloc!
  • 甚至在静态内存中添加static存储类限定符。
【解决方案2】:

当您将其放入main() 时,它会在堆栈上分配 128MB,并且堆栈通常是有限的,该限制因系统而异。有些可能只允许您使用 8MB,而另一些则尽可能多 - 您的限制似乎是 8MB,这是大多数 Linux 平台的标准。如果这是类似 POSIX 的环境,您可以尝试使用 ulimit -s 控制限制。

当您从main() 中取出声明并使其成为静态时,它将最终进入 BSS 段(除非您对其进行初始化),并且在大多数系统上仅受堆空间的限制(通常非常大和/或无限)。见http://en.wikipedia.org/wiki/Data_segment

但是,如果您希望在本地和临时使用它,请考虑自己分配 NR 兆字节:

#define MB (1024*1024)
char *bufp = malloc(NR*MB)
char *buf[NR];
int i;

for (i = 0; i < NR; i++)
  buf[i] = bufp + i*MB;

您也可以单独分配每个 MB 块,但我这样做是为了以防您希望整个区域在内存中是连续的。如果您正在编写一个库以了解您的程序是否会继续执行其他操作,请记住在完成后发送电子邮件至 free(bufp)

【讨论】:

  • +1 将关于 free() 的评论限定为“如果您正在编写一个库,说明您的程序是否会继续执行其他操作。”
【解决方案3】:

您的数组是在堆栈上分配的。堆栈的大小有限(取决于操作系统和链接器设置)。我认为 win32(msvc 编译器)的默认堆栈大小约为 1 兆字节,linux(gcc)为 8 兆字节。任何大于此值的内容都会导致堆栈溢出,从而导致即时段错误。

可能的解决方案:

  1. 在链接器设置中增加堆栈大小。
  2. 动态分配内存(使用 malloc)。
  3. 使数组全局化。
  4. 使数组静态化。

使变量全局/静态将导致(至少在我见过的编译器上)它被分配到堆栈之外 - 无论是在数据段还是代码段中,这不会影响堆栈大小。

【讨论】:

    【解决方案4】:

    或者您可以为您的程序增加堆栈分配大小。例如,在 VS 2008 中,转到 Project Properties -> Linker -> 并设置 Stack Commit Size。

    【讨论】:

    • 我不同意这个想法(但我不会反对你)。堆栈不适合存放大量数据。
    【解决方案5】:

    您可以使用 malloc,通常也可以使用文件范围在 main 之外声明它。如果您在另一个 c 文件中需要它,请查看使用 extern。除非您有充分的理由拥有文件范围变量,否则不建议使用此方法(注意 c 并没有真正的“全局”变量,只有您可以使用 extern 访问的文件范围变量)。 Google 也是您在这些技术上的朋友 :)。您通常还可以找到与您的编译器/操作系统相关的最大堆栈大小设置。寻找“设置堆栈大小”。再次不推荐,学习使用 malloc :) .

    【讨论】:

      【解决方案6】:

      分段错误可能还有其他原因。 使用调试器(例如 gdb)来确定分段错误发生的确切位置。

      【讨论】:

      • -1:不,程序几乎肯定是因为那行而崩溃的。该代码几乎总是会导致崩溃,通常是堆栈溢出错误或分段错误,具体取决于编译器。
      • 只是因为那条线。当我注释掉它时它会正常运行。
      • 如果注释掉,运行正常,具体有什么效果?
      • 我不明白你在问什么。我从代码中删除了该行,程序没有导致分段错误。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-04
      • 2012-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多