如何在C ++中检测segv

时间:2014-04-17 18:58:42

标签: c++

试图在我的小型计算机上构建一个矩阵,数组大小变大,它耗尽了内存容量然后我得到了一个segv,我想知道C ++中是否有办法检测segv而不跳出来然后继续?

unsigned m = 10000;
unsigned n = 10000;
double mat[m][n];
for (unsigned i = 0; i < m; ++i)
{
    for (unsigned j = 0; j < n; ++j)
    {
        double tmpNum1 = rand()%precisionA;
        double tmpNum2 = tmpNum1/precisionA+rand()%precisionB;

        mat[i][j] = tmpNum2;
    }
}

if (segv) // How to do this???
{
    cout<< "Buy a new computer please!" << endl;
}
else
{
    cout<< "Good, get a coffee for yourself!" << endl;
}

Edit1:有时错误是segv,有时是"terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc Aborted (core dumped)" Edit2:在这里使用Ubuntu。

4 个答案:

答案 0 :(得分:7)

10000x10000 double的数组大约为800MB,您将该数组完全放在堆栈上。所以,当然它将是SEGV:我所知道的系统没有分配几乎GB的堆栈内存。

使用new在堆上分配它,它应该可以正常工作。


至于如何捕获SEGV,这是特定于平台的。在某种意义上,SEGV是由程序引起的对未定义行为的许多可能响应之一。捕获SEGV绝不会捕获程序因这种未定义的行为而失败的所有可能方式。

在Windows上,您可以使用structured exception handler来捕获无效访问引发的访问冲突异常。

在POSIX系统上,您可以使用signal handler来捕获SIGSEGV。

但是,请记住,由于堆栈溢出(在这种情况下会发生这种情况),您的程序还有其他方法可能会死亡。您的堆栈可能会增长到目前为止与堆相交,导致堆损坏;您的操作系统可能无法捕获无效访问,并在以后发生无关错误时崩溃; libc可能会在检测到堆栈碎片或任何其他错误后调用abort()。因此,捕获SEGV的最佳方法是首先修复它

答案 1 :(得分:2)

您可以使用signal()函数拦截SIGSEGV等信号:

http://www.cplusplus.com/reference/csignal/signal/

请注意,在您的情况下,您将矩阵分配到程序的堆栈中,这相当小(在Linux上大约为8MB左右)。

您可能希望使用动态分配(new运算符)来分配矩阵。这样做会将矩阵存储到程序堆中,您可以在其中存储更多数据。

答案 2 :(得分:1)

要捕获由operator new(C ++)引起的堆分配失败,您需要在try/catch块上包含对它的调用,然后捕获std::bad_alloc异常。

如果您使用malloc()/calloc()和朋友分配内存,只需检查返回值即可。错误或分配失败时为NULL。

对于由递归,大堆栈分配的数组或alloca()引起的堆栈溢出,有两种方法可以处理我所知道的异常。在Windows上,您可以使用结构化异常处理(SEH)。另一种方法是使用C Signals API

答案 3 :(得分:-1)

您的mat数组无效C ++ 使用new / delete,或std :: array,std :: vector ...
然后你可以捕获预期std :: bad_alloc

(我理解你的意思,但为什么用“segv”这个词?)