为什么在某些机器上堆栈溢出,而在另一台机器上分段错

1N5*_*818 31 c++ stack-overflow segmentation-fault

出于好奇,我正在尝试生成堆栈溢出.此代码根据OP生成堆栈溢出,但是当我在我的机器上运行它时,它会生成分段错误:

#include <iostream>

using namespace std;

int num = 11;
unsigned long long int number = 22;

int  Divisor()
{
    int result;
    result = number%num;

    if (result == 0 && num < 21)
    {
        num+1;
        Divisor();

        if (num == 20 && result == 0)
        {
            return number;
        }
    }

    else if (result != 0)
    {
        number++;
        Divisor();
    }
}

int main ()
{
    Divisor();
    cout << endl << endl;
    system ("PAUSE");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

此外,根据这篇文章,一些例子也应该做同样的事情.为什么我会得到分段错误呢?

Sou*_*osh 26

为什么我会得到分段错误呢?

您所看到的分段错误是堆栈溢出的副作用.的原因是由于堆栈溢出,结果是分段错误.

来自维基百科的文章 "堆栈溢出"(强调我的)

....当一个程序试图使用比调用堆栈上可用空间更多的空间时(也就是说,当它试图访问超出调用堆栈边界的内存时,实际上是缓冲区溢出),堆栈被称为溢出,通常会导致程序崩溃.


Sad*_*que 16

堆栈溢出可能导致以下错误:

  • SIGSEGV (分段违规)信号用于该过程.
  • SIGILL (非法指令)信号.
  • SIGBUS 访问无效地址.

有关更多读取程序错误信号.由于行为未定义,因此上述任何一种都可以出现在不同的系统/体系结构上.


Lun*_*din 13

你本质上是在问:未定义行为的行为是什么?

答案是:未定义的行为是未定义的行为.什么都可能发生.

研究为什么在特定系统上获得某种未定义的行为通常是毫无意义的练习.

未定义,未指定和实现定义的行为

在堆栈溢出的情况下,程序可能会覆盖RAM中的其他变量,或者破坏运行函数自身的返回地址,或者尝试修改其给定地址范围之外的内存等.根据系统的不同,您可能会遇到硬件异常和各种错误信号如SIGSEGV(在POSIX系统上),或突然程序崩溃,或"程序似乎工作正常",或其他.

  • 你的论点不清楚.递归不是错误的程序构造,也不涉及错误的数据.标准(我在思考C++,但在这一点上C类似)完美地描述了如何处理递归调用.由于运行时堆栈上缺少空间而尝试函数调用可能会失败,所以我觉得徒劳无功(而动态内存耗尽的可能性明显得到满足,而且本身并不会导致UB); 也许我看错了地方.标准似乎指定无限重复,如在循环中,而不是UB (2认同)
  • 是."如果它不符合标准,我就不在乎"是一种非常无益的态度.现实世界存在. (2认同)

mer*_*011 11

发布的其他答案都是正确的.

但是,如果你的问题的目的是要理解为什么你没有看到一个打印错误,指出堆栈溢出已经发生,答案是一些运行时库显式检测并报告堆栈溢出,而其他人没有,并且只是崩溃与段错误.

特别是,看起来至少某些版本的Windows检测到Stackoverflow并将它们转换为异常,因为文档建议您可以处理它们.


nos*_*nos 7

堆栈溢出是一个原因,结果就是分段错误.

在linux和其他类似unix的系统上,分段错误可能是堆栈溢出的结果.您没有得到程序遇到堆栈溢出的任何特定信息.

在您链接的第一篇文章中,该人正在Windows上运行可能表现不同的代码,例如,特别检测堆栈溢出.


Min*_*s97 5

我猜你正在使用没有启用堆栈检查的编译器.

堆栈检查是一个相当简单的机制,它会杀死程序,指出堆栈指针飞过堆栈绑定后发生堆栈溢出.它通常被禁用用于优化目的,因为程序几乎肯定会在堆栈溢出时崩溃.

为什么是段错误?好吧,如果没有启用堆栈检查,您的程序在用完堆栈后不会停止,并继续直接进入不相关(并且经常受到保护)的内存,它会尝试修改以用作新函数调用的另一个堆栈帧.疯狂随之发生,并发生了一个段错误.

  • 通常,有意确保刚好超过堆栈末尾的内存未映射,因此您不会进入例如malloc()ed数据结构. (2认同)