C 为什么在编译时声明数组大小时会受到限制?

C 为什么在编译时声明数组大小时会受到限制?,c,arrays,memory-management,local-variables,C,Arrays,Memory Management,Local Variables,比如我能做什么 int *arr; arr = (int *)malloc(sizeof(int) * 1048575); 但如果程序不崩溃,我无法做到这一点: int arr[1048575]; 为什么会这样?假设arr是一个局部变量,将其声明为数组将使用(相对有限的)堆栈中的内存,而malloc()使用(相对无限的)堆中的内存。如果在函数中将它们作为局部变量分配(这是唯一一个可以在指针声明后紧接着调用malloc的地方),区别在于malloc将从堆中分配一块内存并给出其地址,同时直接执行

比如我能做什么

int *arr;
arr = (int *)malloc(sizeof(int) * 1048575);
但如果程序不崩溃,我无法做到这一点:

int arr[1048575];

为什么会这样?

假设
arr
是一个局部变量,将其声明为数组将使用(相对有限的)堆栈中的内存,而
malloc()
使用(相对无限的)堆中的内存。

如果在函数中将它们作为局部变量分配(这是唯一一个可以在指针声明后紧接着调用
malloc
的地方),区别在于
malloc
将从堆中分配一块内存并给出其地址,同时直接执行
int-arr[1048575];
将尝试在堆栈上分配内存。堆栈的可用空间要少得多

堆栈的大小受到限制,原因有两个,我知道:

  • 传统的命令式编程很少使用递归,因此深度递归(和沉重的堆栈增长)“可能”是无限递归的标志,因此是一个会杀死进程的错误。因此,最好在进程消耗千兆字节虚拟内存(在32位体系结构上)之前捕获它这将导致进程耗尽其地址空间(此时机器使用的虚拟内存可能远远超过其实际拥有的RAM,因此运行非常缓慢)
  • 多线程程序需要多个堆栈。因此,运行时系统需要知道堆栈永远不会超过某个界限,因此,如果创建了新线程,它可以在该界限之后放置另一个堆栈

  • 声明数组时,将其放置在堆栈上

    调用malloc()时,内存从堆中获取

    与堆相比,堆栈通常更有限,并且通常是暂时的(但这取决于您进入和退出声明此数组的函数的频率)


    对于如此大的内存(可能不是按照今天的标准?)来说,假设您希望数组能够持续一段时间,则最好对其进行malloc处理。

    不需要指针指向堆中的内存,它可以指向堆栈或块存储中的内存。@Jay:这是正确的。但是,根据定义,
    malloc()
    始终从堆中分配内存。还有其他函数(例如
    alloca()
    )从堆栈中分配内存。除非声明为静态,否则本地数组的声明将始终从堆栈中分配内存。全局数组是从堆中分配的。我想我的问题是,为什么堆栈的可用空间要少得多。我认为堆栈和堆都有相同的增长空间,而且它们都有相同的增长空间只是在概念上(以及在简单的系统中)彼此成长(向下堆叠和向上堆叠)的确如此。但在复杂的多线程系统中,每个线程都需要自己的堆栈,而堆空间可以共享。这里有更多信息:我想我的问题是为什么堆栈的可用空间要少得多。我认为堆栈和堆都有相同的增长空间,它们只是相互增长而已(堆栈向下和堆向上。)@ladookie:我添加了一些信息,说明了为什么堆栈大小与堆相比如此有限。这是在全局范围还是在函数范围内?