在visual studio C++中,有没有任何方法可以在运行时增加堆栈保留大小
Is there any way to increase stack reserve size in running time in visual studio C++
我正在C++中开发一个.exe求解器。求解器中有一个递归算法,所以我在"配置属性"->"链接器"->"系统"->"堆栈保留大小"中将堆栈保留大小设置为2 100 000 000。但当一些客户在他们的机器上运行它时,它就会崩溃。它在大多数机器上运行良好。我将堆栈保留大小减小到0,并要求客户尝试一下。这很有效。所以我认为堆栈保留大小应该是个问题。
现在我有两个问题:
-
客户机器的潜在问题是什么?我认为客户可能设置了一个非常小的虚拟内存最大大小。所以我在我的机器上尝试了一下,在高级系统设置->性能设置->高级->虚拟内存->客户大小中将虚拟内存的最大大小设置为0。但在这种情况下,解算器不会崩溃。
-
有没有办法在运行时设置堆栈保留大小。如果可以,那么如果求解器在客户的机器上崩溃,我可以让客户用ENV覆盖堆栈大小。
PS:添加更多信息。此代码编译为64位,没有设置LARGEADDRESSAWARE选项(我不知道该选项的默认设置)。这段代码在64位机器上运行得几乎很好。事实上,在过去几年里,只有一位客户抱怨这次撞车事故。
将堆栈大小设置为2GB是解决此问题的荒谬方法。正确的解决方案是减少递归算法中的堆栈使用,或者使用迭代解决方案(可能使用软件堆栈来解决递归为您解决的"我们要回到哪里"问题)。
一个相对简单的解决方案是,在不知道代码实际做什么的情况下,使用std::vector<T> v(size);
而不是T v[size];
——这将使v
的大小大约为指针的3*大小,而不是堆栈上的sizeof(T) * size
——如果你有几个更大的数组,这确实是减少堆栈使用的一种有用方法。
崩溃的原因是操作系统加载程序在尝试为新进程设置初始线程时,未能找到2.1GB的连续地址空间来为线程堆栈分配(保留,而不是提交)。
此故障是不确定的,因为地址空间布局随机化(一种安全功能)会导致DLL以随机地址加载,从而导致地址空间碎片。幸运的是,有一个足够大的片段可以用于线程堆栈。否则,在任何代码执行之前都会立即崩溃。
更改虚拟内存设置并不重要,因为问题在于地址空间,而不是所有进程的最大虚拟内存总量。
根据你的描述,我的水晶球显示:
- 您的代码使用
/LARGEADDRESSAWARE
选项编译为32位代码 - 您的代码在运行32位版本Windows的计算机上始终崩溃
- 您的代码有时可以工作,但在运行64位Windows或带有
/3GB
boot.ini选项的32位Windows的计算机上启动时经常崩溃
正如Cyber所说,您应该设计代码以使用更少的堆栈空间。Mats在他的回答中给出了一些实用的建议。
至于在运行时设置堆栈保留,是的,这是可能的,使用CreateThread
的第二个参数。基本上,您将主线程保留为一个小堆栈(例如,默认大小),然后使用所需大小调用CreateThread
,并从新线程执行所有操作。但不要这样做,而是要修复高得离谱的堆栈使用率。
- CMake-按正确顺序将项目与C运行时对象文件链接
- 我在c++代码中生成了一个运行时#3异常
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 删除指向指针的指针是运行时错误吗
- 如何用参数值调用函数(仅在运行时已知)
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- c++中的指针和运行时错误
- 在运行时处理类型擦除的数据-如何不重新发明轮子
- 有没有一种方法可以测量c++程序的运行时内存使用情况
- 建议在运行时将带有类实例的列表从c++导入qml
- 无法理解此 return 语句的功能,没有它就会发生运行时错误
- 如何在GTK程序运行时禁用屏幕保护程序/电源管理/屏幕消隐
- 在同一模拟中使用静脉和静脉_ inet内容时出现运行时错误
- 读取文件时运行时的未知行为
- 在不使用容器或字符串库的情况下,在运行时增加动态数组大小
- 如何让变量在每次运行时增加 "return main();"
- 为什么未达到的 try-catch 块会增加运行时时间
- 在visual studio C++中,有没有任何方法可以在运行时增加堆栈保留大小
- 如何在运行时增加结构数组的大小