我的程序在Windows计算机上崩溃,但在Linux上运行正常

时间:2019-02-06 21:59:16

标签: c++ c linux windows stack-overflow

我试图在笔记本电脑(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));
}

2 个答案:

答案 0 :(得分:2)

听起来像是堆栈粉碎,或更准确地说是stack buffer overflow,这是您收到的错误消息。该函数的深度很大,并且会继续将变量压入堆栈。如果将足够多的变量压入堆栈,它将粉碎。从堆栈的声音来看,计算机没有无限的存储空间。

给出足够大的输入,如果优化得不好,它应该堆叠任何粉碎(并且仍然可能仍然)。在不了解编译器的情况下,如何禁用它尚无一个全面的选择,但是如果您使用的是Microsoft Visual Studio的编译器套件,则可以禁用保护if I understand this doc correctly

  1. 在解决方案资源管理器中,右键单击该项目,然后单击“属性”
  2. 在“属性页”对话框中,单击C / C ++文件夹。
  3. 单击“代码生成”属性页。
  4. 修改“缓冲区安全性检查”属性。

作为警告,这不安全,并且可能会发生不好的事情,因此使用此方法后果自负。

答案 1 :(得分:1)

在Visual Studio中,默认堆栈大小为1 MB,因此递归深度为65535,并且我相信,此类型的x64上的调用方/函数的最小堆栈帧为72字节,因此您将用完您的程序可用的堆栈框架空间(我计算出此方案所需的几乎4.5Mb堆栈)。这也产生了堆栈缓冲区溢出错误,与堆栈粉碎无关,除了编译时超出了程序可用的最大堆栈大小。

包括Visual Studio在内的大多数编译器都可以让您指定堆栈大小。

更多详细信息: https://docs.microsoft.com/en-us/cpp/build/reference/f-set-stack-size?view=vs-2017

[编辑以反映65,535帧,而不是14亿帧]