提问人:Patrick McDonald 提问时间:2/21/2009 最后编辑:Patrick McDonald 更新时间:1/10/2018 访问量:19952
声明大型数组时出现堆栈溢出异常
Getting a stack overflow exception when declaring a large array
问:
以下代码为我生成堆栈溢出错误
int main(int argc, char* argv[])
{
int sieve[2000000];
return 0;
}
我该如何解决这个问题?我正在使用 Turbo C++,但想将我的代码保留在 C 中
编辑:
谢谢你的建议。上面的代码只是举例来说,我实际上在函数中声明数组,而不是在 sub main 中声明数组。此外,我需要将数组初始化为零,所以当我在谷歌上搜索 malloc 时,我发现 calloc 非常适合我的目的。
与在堆栈上分配相比,Malloc/calloc 还有一个优势,即允许我使用变量声明大小。
答:
您的数组太大,无法放入堆栈中,请考虑使用堆:
int *sieve = malloc(2000000 * sizeof(*sieve));
如果您确实想更改堆栈大小,请查看此文档。
提示: - 不要忘记在不再需要动态分配的内存时释放它。
评论
最好将其分配在堆上,而不是堆栈上。类似的东西
int main(int argc, char* argv[])
{
int * sieve;
sieve = malloc(20000);
return 0;
}
评论
sieve = malloc(20000 * sizeof *sieve)
int
这大约是 7MB 的堆栈空间。在 Visual Studio 中,可以使用 /STACK:###,### 来反映所需的大小。如果你真的想要一个巨大的堆栈(这可能是一个很好的理由,使用LISP或其他:)的东西,在强制你使用VirtualAlloc之前,即使堆也仅限于小的分配),你可能还想将你的PE设置为使用/LARGEADDRESSAAWARE(再次是Visual Studio的链接器)进行构建,但这会配置你的PE头文件,以允许你编译的二进制文件寻址完整的4GB的32位地址空间(如果在WOW64中运行)。如果生成真正庞大的二进制文件,通常还需要将 /bigobj 配置为额外的链接器参数。
如果你仍然需要更多的空间,你可以通过使用类似于(同样是 MSVC 的链接)/merge: 的东西来从根本上违反约定,这将允许你将一个部分打包到另一个部分,这样你就可以将每个字节用于单个共享代码/数据部分。当然,您还需要在 def 文件中或使用 #pgrama 配置 SECTIONS 权限。
有 3 种方法:
- 在堆上分配数组 - 使用,正如其他海报所建议的那样。不要忘记它(尽管这并不那么重要 - 操作系统将在程序终止时为您清理内存)。
malloc()
free()
main()
- 在单位级别声明数组 - 它将在数据段中分配,并且对每个人都可见(添加到声明将限制对单位的可见性)。
static
- 将数组声明为 - 在这种情况下,它将在数据段中分配,但仅在 中可见。
static
main()
评论
main()
malloc()
有没有原因不能使用 alloca() 根据对象实际需要的大小在堆栈框架上分配所需的空间?
如果你这样做了,但仍然破坏了堆栈,把它放在分配的堆里。我强烈建议不要在 main() 中将其声明为静态并将其放在数据段中。
如果它真的必须那么大,而你的程序不能在堆上分配它,那么你的程序一开始就没有在这种类型的机器上运行的业务。
你(确切地)想完成什么?
评论
使用 malloc。全部检查返回类型是否为 null,如果它为 null,则您的系统根本没有足够的内存来容纳那么多值。
你的阵列很大。
您的计算机或操作系统可能没有或不想分配这么多内存。
如果你绝对需要一个巨大的数组,你可以尝试动态分配它(使用 ),但这样你就有泄漏内存的风险。不要忘记释放内存。malloc(...)
malloc 的优点是它尝试在堆上分配内存,而不是在堆栈上分配内存(因此您不会得到堆栈溢出)。
您可以检查 malloc 返回的值,以查看分配是成功还是失败。 如果失败了,只需尝试 malloc 一个较小的数组。
另一种选择是使用可以动态调整大小的不同数据结构(如链表)。此选项是否有效取决于您将如何处理数据。
另一种选择是将内容存储在文件中,即时流式传输数据。这种方法是最慢的。
如果您要在硬盘驱动器上存储,您不妨使用现有的库(用于数据库)
由于 Turbo C/C++ 是 16 位编译器,int 数据类型消耗大约 2 个字节。 2字节*2000000=40,00,000字节=3.8147MB空间。
函数的自动变量存储在堆栈中,它导致了堆栈内存的溢出。相反,使用数据存储器 [使用静态或全局变量] 或动态堆内存 [使用 malloc/calloc] 根据处理器内存映射的可用性创建所需的内存。
评论