在C ++中使用C动态内存函数来避免分段错误

时间:2011-09-28 14:26:07

标签: c++ posix

我试图安全地从我希望发生的分段错误中恢复过来。我试图避免使用我的canAlloc()函数进行检查。当canAllow返回false时,A0(如果你没有看到它就是Ackermann)应该抛出一个我可以在main方法中捕获的异常。 checkTable和saveInTable都是使用map<int hash, int value>来存储A0返回的函数。

    bool canAlloc(){
     bool reBool = false;
     int * memch = (int*)calloc (10000, sizeof(int));
     reBool = (memch != NULL);
     free(memch);
     return reBool;
    }


    int A0(int m, int n){
if(!canAlloc()) throw;

int reInt = checkReturnTable(m,n);
if(reInt == -1){        
    if(m == 0){
        return n + 1;
    } else if(m > 0){
           if(n == 0){
                reInt = A0(m-1,1);
           } else if(n > 0){
                reInt = A0(m-1, A0(m,n-1));
           }
    }
    saveInReturnTable(m,n,reInt);
    return reInt;
} else return reInt;
}

来自评论:

  

在main中,我有一个try-catch块来捕获任何异常try{} catch(...){}。据我了解,这三个时期应该捕获任何抛出的异常。据我所知,throw关键字抛出异常而没有任何说明符,但仍然可以被三个点捕获。

2 个答案:

答案 0 :(得分:4)

分段错误不是C ++异常。它表示程序故障导致操作系统向您的进程发送SIGSEGV信号。您将无法直接catch SIGSEGV信号;你必须设置一个信号处理程序......好吧,在那一点上它变得棘手,因为你不清楚你是否可以从信号处理程序中抛出异常。

没有指定异常的throw重新抛出当前异常;它只在catch块内有意义。

当系统无法进一步扩展堆栈时,您可能会得到SIGSEGV,可能是因为您的虚拟内存不足。这意味着你的一个函数调用失败了,因为没有空间来放置它的参数或局部变量或返回地址等。没有干净的方法可以从中恢复,这就是系统生成分段错误的原因。

如果故障是因为calloc()无法分配内存,则不会出现分段错误;你会得到零回报值。并且当它发生时,你可以干净地同步地提出“内存不足”异常。但这不是你的问题。

答案 1 :(得分:1)

您无法从分段错误中恢复,因为一旦发生故障,您的程序就不再处于定义良好的状态,并且没有机制可以回滚到定义良好的状态,任

分段错误总是以某种方式出现编程错误,您必须简单地避免它。在C ++中,您可以简单地捕获来自动态分配的异常:

 T * p;
 try { p = new T; }
 catch(const std::bad_alloc & e) { /* ... */ }

通常没有必要那么手动,因为你将动态分配包装在合适的管理容器(如unique_ptrshared_ptr)中,你应该捕获异常(甚至不是在你的程序流程中你可以处理错误并继续有意义的点。

(由于例外情况,您通常不需要在呼叫方面检查可能抛出函数的结果 - 这是使用异常的全部要点。)


如果由于某种原因你只想分配原始内存而不构造任何对象,你可以用两种方式来做:

// Method #1, the C++ way:
void * addr = ::operator new(n);  // will throw std::bad_alloc on error

// Method #2, the manual way:
void * addr = std::malloc(n);
if (!addr) throw std::bad_alloc();  // throw exception manually, handled elsewhere