限制在 C 语言中将内存分配给堆栈上的数组?

Limit for memory allocation to an array on stack in C?

提问人:tycoon 提问时间:4/21/2022 更新时间:4/21/2022 访问量:289

问:

我不知道如何问这个问题,因为它对我来说有点令人困惑。我遇到此代码问题

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

#define ull unsigned long long

#define SIZE 1000000001

#define min(a,b) ((a<b?a:b))
#define max(a,b) ((a>b?a:b))

int solve(void) {

//    unsigned *count = malloc(sizeof(unsigned) * SIZE);
    int k;
    scanf("%d", &k);
    unsigned count[SIZE];
    for (ull i = 0; i < SIZE; i++){
        count[i] = 0;
    }

    return 0;
}

int main(void){
    unsigned t;
    if (scanf("%u", &t) != 1) return 1;
    while (t-- > 0){
        if (solve() != 0) return 1;
    }
}

对我来说,这段代码给出了段错误。

我的观察是什么

  1. 它运行良好,直到它处于求解函数中。
  2. 在调用 solve 函数时,它给出了段错误。
  3. 它与删除此行会产生相同的错误无关scanf("%d", &k)
  4. 但是,如果我们减小 SIZE 值,它将运行良好。
  5. 我可以做的另一件事是,我可以使用堆,而不是在堆栈上创建数组,这工作正常。
  6. 如果我只在求解函数中声明数组,而不是将 k 作为输入并将数组的所有值初始化为 0。我没有得到任何段错误countcount

所以我对此有一些疑问。

  • 这是由于数组的内存限制还是由于函数求解的堆栈帧的内存限制(或者可能是我找不到的其他原因)。
  • 如果这是由于任何类型的内存限制造成的,那么对于程序来说,它是不是太低了?
  • 编译器如何检查诸如添加任何类型的打印语句之类的错误不会在数组声明之前运行,因为当程序到达时我遇到段错误。因此,编译器以某种方式知道代码存在问题,甚至没有到达那里。solve
  • 特别是对于第 6 点,根据我的知识,在声明数组时,它为数组保留了内存。因此,通过初始化它,我没有做任何事情,这将增加数组的大小。那么为什么我在声明数组时没有得到任何类型的错误,而当我在数组中初始化所有这些值时,我得到了段错误

也许我以完全错误的方式看待它,但这就是我的想法,所以如果你知道任何原因,请也回答我

数组 C

评论

5赞 Yunnosch 4/21/2022
假设局部变量有 4GB 的可用内存似乎相当乐观。
1赞 Some programmer dude 4/21/2022
堆栈相当有限。在 Windows 上,每个进程的默认堆栈大小仅为 1 MiB,而在 Linux 上为 8 MiB。如果需要大量数据,请动态分配。使用不同的数据结构。
1赞 yano 4/21/2022
在 Linux 上,您可以使用 ulimit -a 查找堆栈大小。实际上,在我的 Fedora 盒子上只显示我的堆栈大小,即 8MB。ulimit -s
2赞 Some programmer dude 4/21/2022
另一方面,您似乎正在为某种所谓的“竞赛”或“在线评委”网站编写代码。不要将其用于任何学习或教学的孩子,这不是他们的目的。他们没有正确地教你编程语言,他们没有教任何类型的计算机科学或其背后的数学,他们没有教任何其他有用的技术,这些技术是程序员成功的必备知识。他们教的代码都是糟糕的(有时甚至是无效的),以及如何“聪明”(这几乎从来都不是编写好程序的好特质)。买书,上课,留在学校。
2赞 Some programmer dude 4/21/2022
你会得到未定义的行为。这可能会导致崩溃,或者可能导致您的房子着火,或者看起来工作得很好(只有在您最意想不到的时候才坏掉)。

答:

4赞 Revanth N Mallol 4/21/2022 #1

这取决于您的操作系统。在 Windows 上,堆栈的典型最大大小为 1MB,而在典型的现代 Linux 上为 8MB,尽管这些值可以通过各种方式进行调整。 对我来说,它工作正常,请与其他平台或其他系统进行检查。