我试图安全地从我希望发生的分段错误中恢复过来。我试图避免使用我的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
关键字抛出异常而没有任何说明符,但仍然可以被三个点捕获。
答案 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_ptr
或shared_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