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

时间:2015-05-20 09:04:53

标签: c++ segmentation-fault stack-overflow

出于好奇,我正在尝试生成堆栈溢出。此代码生成堆栈溢出according to the 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;
}

另外,根据this帖子,一些例子也应该这样做。为什么我会得到分段错误呢?

6 个答案:

答案 0 :(得分:26)

  

为什么我会收到细分错误?

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

来自wikipedia article的“堆栈溢出”(强调我的

  

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

答案 1 :(得分:16)

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

    该进程的
  • SIGSEGV(分段违规)信号。
  • SIGILL(非法指令)信号。
  • SIGBUS访问无效地址。

更多阅读Program Error Signals。由于行为未定义,因此上述任何一种都可以出现在不同的系统/体系结构中。

答案 2 :(得分:13)

您实质上是在问:未定义行为的行为是什么?

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

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

Undefined, unspecified and implementation-defined behavior

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

答案 3 :(得分:11)

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

但是,如果您的问题的目的是要理解为什么您没有看到表明发生堆栈溢出的打印错误,答案是某些运行时库显式检测并报告堆栈溢出,而其他运行时库则没有,简单地用段错误崩溃。

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

答案 4 :(得分:7)

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

在Linux和其他类似unix的系统上,segmentation fault可能是堆栈溢出的结果。您没有得到程序遇到堆栈溢出的任何特定信息。

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

答案 5 :(得分:5)

我猜您正在使用未启用stack checking的编译器。

堆栈检查是一种相当简单的机制,它会在堆栈指针飞过堆栈边界时立即杀死程序,指出 Stack Overflow Happened 。它经常被禁用用于优化目的,因为程序几乎肯定会在堆栈溢出时崩溃。

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