我的程序在 Windows 机器上崩溃,但在 Linux 机器上运行良好
My program crashes on the Windows machine yet it works fine on the Linux
我尝试在我的笔记本 (Win10) 上编写 Ackermann 函数,但是程序在更高的值时崩溃,而不是继续计算几分钟或几小时。
我的朋友在他的机器(SUSE)上尝试了相同的代码,它工作得很好,然后我们在学校服务器(CentOS)上尝试了它,它又崩溃了。
编辑:它也在服务器上工作,只需要再试一次。它也适用于我们尝试过的另一台服务器......所有这些都在 Linux.
上
我们怀疑它背后是堆栈溢出,但这很奇怪,因为值还没有那么高。那我怎么能在这个系统上执行递归函数呢?
谢谢大家的回答。我只是好奇它为什么会发生以及如何让它在我的机器上工作。
我尝试同时使用 C 和 C++,但没有任何变化。
#include <stdio.h>
int ackermann (int m, int n);
int main () {
int m = 4;
int n = 1;
return ackermann(m,n);
}
int ackermann (int m, int n)
{
if (m == 0) return n=n+1;
else if (m > 0 && n == 0) return ackermann(m-1,1);
else if (m > 0 && n > 0) return ackermann(m-1,ackermann(m,n - 1));
}
听起来像是堆栈崩溃,或者更准确地说是 stack buffer overflow,这就是您收到的错误消息。该函数具有非常大的深度,并且会不断将变量压入堆栈。如果你将足够多的变量压入堆栈,它就会崩溃。计算机没有无限的堆栈内存,从它的声音来看,也不是一个疯狂的数量。
给定足够大的输入,如果没有优化好,它应该堆叠任何粉碎(并且仍然可能无论如何)。在不了解您的编译器的更多信息的情况下,无法提供有关如何禁用它的综合选项,但如果您使用的是 Microsoft Visual Studio 的编译器套件,则可以禁用保护 if I understand this doc correctly。
- 在解决方案资源管理器中,右键单击该项目,然后单击“属性”
- 在 属性 页面对话框中,单击 C/C++ 文件夹。
- 单击“代码生成”属性 页面。
- 修改缓冲区安全检查属性。
作为警告,这不安全并且可能会发生不好的事情,所以使用它需要您自担风险。
在 Visual Studio 中,默认堆栈大小为 1 MB,因此递归深度为 65535,而且我相信,这种类型的 x64 上 caller/function 的最小堆栈帧为 72 字节,因此您将 运行 超出程序的可用堆栈框架 space (我计算出此场景所需的堆栈将近 4.5Mb)。这也会产生堆栈缓冲区溢出错误,并且与堆栈粉碎无关,除非您在编译时超出了程序可用的最大堆栈大小。
包括 Visual Studio 在内的大多数编译器都允许您指定堆栈大小。
更多详情:
https://docs.microsoft.com/en-us/cpp/build/reference/f-set-stack-size?view=vs-2017
[编辑以反映 65,535 帧,而不是 14 亿帧]
我尝试在我的笔记本 (Win10) 上编写 Ackermann 函数,但是程序在更高的值时崩溃,而不是继续计算几分钟或几小时。
我的朋友在他的机器(SUSE)上尝试了相同的代码,它工作得很好,然后我们在学校服务器(CentOS)上尝试了它,它又崩溃了。
编辑:它也在服务器上工作,只需要再试一次。它也适用于我们尝试过的另一台服务器......所有这些都在 Linux.
上我们怀疑它背后是堆栈溢出,但这很奇怪,因为值还没有那么高。那我怎么能在这个系统上执行递归函数呢?
谢谢大家的回答。我只是好奇它为什么会发生以及如何让它在我的机器上工作。
我尝试同时使用 C 和 C++,但没有任何变化。
#include <stdio.h>
int ackermann (int m, int n);
int main () {
int m = 4;
int n = 1;
return ackermann(m,n);
}
int ackermann (int m, int n)
{
if (m == 0) return n=n+1;
else if (m > 0 && n == 0) return ackermann(m-1,1);
else if (m > 0 && n > 0) return ackermann(m-1,ackermann(m,n - 1));
}
听起来像是堆栈崩溃,或者更准确地说是 stack buffer overflow,这就是您收到的错误消息。该函数具有非常大的深度,并且会不断将变量压入堆栈。如果你将足够多的变量压入堆栈,它就会崩溃。计算机没有无限的堆栈内存,从它的声音来看,也不是一个疯狂的数量。
给定足够大的输入,如果没有优化好,它应该堆叠任何粉碎(并且仍然可能无论如何)。在不了解您的编译器的更多信息的情况下,无法提供有关如何禁用它的综合选项,但如果您使用的是 Microsoft Visual Studio 的编译器套件,则可以禁用保护 if I understand this doc correctly。
- 在解决方案资源管理器中,右键单击该项目,然后单击“属性”
- 在 属性 页面对话框中,单击 C/C++ 文件夹。
- 单击“代码生成”属性 页面。
- 修改缓冲区安全检查属性。
作为警告,这不安全并且可能会发生不好的事情,所以使用它需要您自担风险。
在 Visual Studio 中,默认堆栈大小为 1 MB,因此递归深度为 65535,而且我相信,这种类型的 x64 上 caller/function 的最小堆栈帧为 72 字节,因此您将 运行 超出程序的可用堆栈框架 space (我计算出此场景所需的堆栈将近 4.5Mb)。这也会产生堆栈缓冲区溢出错误,并且与堆栈粉碎无关,除非您在编译时超出了程序可用的最大堆栈大小。
包括 Visual Studio 在内的大多数编译器都允许您指定堆栈大小。
更多详情: https://docs.microsoft.com/en-us/cpp/build/reference/f-set-stack-size?view=vs-2017
[编辑以反映 65,535 帧,而不是 14 亿帧]