Arrays 数组太大会导致Visual Studio中的堆栈溢出错误和Atom中的块
我的程序是一个具有任意参数的非常简单的随机数生成器。我在Windows10上使用Atom。代码如下:Arrays 数组太大会导致Visual Studio中的堆栈溢出错误和Atom中的块,arrays,c,visual-studio,windows-10,atom-editor,Arrays,C,Visual Studio,Windows 10,Atom Editor,我的程序是一个具有任意参数的非常简单的随机数生成器。我在Windows10上使用Atom。代码如下: #include <stdio.h> #include <stdlib.h> #include <math.h> #define LEN 560000 void main() { int x[LEN]; int i; int m = 1234234; int a = 1245; int c = 3;
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define LEN 560000
void main() {
int x[LEN];
int i;
int m = 1234234;
int a = 1245;
int c = 3;
x[0] = 1;
for (i = 1; i < LEN - 2; i++) {
x[i + 1] = a * (x[i] + c) % m;
}
printf("%lf\n", ((double)x[LEN-5]) / m); /* as check */
}
我没有收到来自终端的任何信息,但是如果我更改了我想要生成的向量的长度,设置LEN=500000,我会立即得到最终输出,即带有来自终端的注释的输出。此外,如果我将Visual Studio与相同的代码一起使用,则会收到由于溢出而导致的错误
我不明白为什么如果我从LEN=500000到LEN=560000,程序就不会执行
以我的拙见,我认为在Atom和Visual Studio这两个编译器中应该有一个数组长度的截止值,因为如果我将数组延长一点,程序就不能工作
编辑:第二个循环从1变为LEN-2,但问题仍然存在。您在main中分配了超过2兆字节的自动存储。这是否超出应用程序可用的堆栈空间并导致堆栈溢出取决于系统。您正在经历未定义的行为,这似乎仅在您访问具有高索引值的x元素时才表现出来,但您定义的对象具有超过可用堆栈空间的自动存储这一事实就足以调用未定义的行为 运行此程序时,您可以尝试修改初始堆栈大小,但没有可移植的方法来指定它:查看系统文档以了解如何执行此操作 对于可移植解决方案,应使用malloc分配数组,并使x成为指向int的指针:
您在main中分配了超过2兆字节的自动存储。这是否超出应用程序可用的堆栈空间并导致堆栈溢出取决于系统。您正在经历未定义的行为,这似乎仅在您访问具有高索引值的x元素时才表现出来,但您定义的对象具有超过可用堆栈空间的自动存储这一事实就足以调用未定义的行为 运行此程序时,您可以尝试修改初始堆栈大小,但没有可移植的方法来指定它:查看系统文档以了解如何执行此操作 对于可移植解决方案,应使用malloc分配数组,并使x成为指向int的指针:
堆栈溢出?局部变量通常存储在堆栈上,包括整个数组的数组。在Windows上,每个进程的默认堆栈是单个MiB。假设sizeofint==4,您的数组将占用超过2个MiB,这在任何现代PC类系统上都是如此。还要记住,C中的数组索引是基于零的,这意味着LEN元素数组的索引将从0到LEN-1(包括0到LEN-1)。由于您使用的是基于一个的索引,因此您将超出范围,并具有未定义的行为。最后,有点吹毛求疵:Atom不是编译器,而是文本编辑器。它具有调用外部程序的功能,例如编译器,但它本身不是编译器。Visual Studio也不是,它是一个IDE,基本上是一个具有项目管理和其他功能的非常专业的编辑器,但它本身也不是编译器,而是依赖外部程序进行编译。编译器的责任不是保护您免受未定义行为的影响,而是您作为程序员的责任。因为C标准甚至没有提到堆或堆栈,所以C本身无法防止资源溢出。递归也有同样的问题:堆栈溢出不是由语言捕获的,而是由OS捕获的。堆栈溢出?局部变量通常存储在堆栈上,包括整个数组的数组。在Windows上,每个进程的默认堆栈是单个MiB。假设sizeofint==4,您的数组将占用超过2个MiB,这在任何现代PC类系统上都是如此。还要记住,C中的数组索引是基于零的,这意味着LEN元素数组的索引将从0到LEN-1(包括0到LEN-1)。由于您使用的是基于一个的索引,因此您将超出范围,并具有未定义的行为。最后,有点吹毛求疵:Atom不是编译器,而是文本编辑器。它具有调用外部程序的功能,例如编译器,但它本身不是编译器。Visual Studio也不是,它是一个IDE,基本上是一个具有项目管理和其他功能的非常专业的编辑器,但它本身也不是编译器,而是依赖外部程序进行编译。编译器的责任不是保护您免受未定义行为的影响,而是您作为程序员的责任。因为C标准甚至没有提到堆或堆栈,所以C本身无法防止资源溢出。递归也有同样的问题:堆栈溢出不是由语言捕获的,而是由操作系统捕获的。您的答案很可靠,但让我告诉您一些事情。我刚刚尝试了这个在线IDEA
nd代码在LEN=1000000时可以完美执行,但是当我选择LEN=4000000时,我得到了一个分段错误。此外,这个web IDE要求main是int。此外,我知道malloc/calloc是分配内存的更好方法,但我想尝试一个最小的程序。事实上,现在该程序甚至可以在Atom中使用更大的数组。@Siderius:这可能只是意味着其他编译器/链接器的最大堆栈大小有更高的默认设置。@AndreasWenzel,正如我以粒子物理的方式写的,内存被切断了。但是malloc与堆栈相关吗?@Siderius:不,用malloc分配的内存是在所谓的堆上分配的,而非静态局部变量是在堆栈上分配的。你的答案很可靠,但让我告诉你一些事情。我刚刚尝试过这个在线IDE,代码在LEN=1000000时执行得非常完美,但是当我选择LEN=4000000时,我得到了一个分段错误。此外,这个web IDE要求main是int。此外,我知道malloc/calloc是分配内存的更好方法,但我想尝试一个最小的程序。事实上,现在该程序甚至可以在Atom中使用更大的数组。@Siderius:这可能只是意味着其他编译器/链接器的最大堆栈大小有更高的默认设置。@AndreasWenzel,正如我以粒子物理的方式写的,内存被切断了。但是malloc与堆栈相关吗?@Siderius:不,用malloc分配的内存分配在所谓的堆上,而非静态局部变量分配在堆栈上。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define LEN 560000
int main() {
int *x = malloc(sizeof(*x) * LEN);
int i;
if (x == NULL) {
fprintf(stderr, "memory allocation failure\n");
return 1;
}
int m = 1234234;
int a = 1245;
int c = 3;
x[0] = 1;
for (i = 1; i < LEN - 2; i++) {
x[i + 1] = a * (x[i] + c) % m;
}
printf("%lf\n", ((double)x[LEN]) / m); /* as check */
free(x);
return 0;
}