如何在Visual Studio 2008 C ++中捕获除零错误(而不是其他错误;以及能够访问异常信息)?
我试过了:
try {
int j=0;
int i= 1/j;//actually, we call a DLL here, which has divide-by-zero
} catch(std::exception& e){
printf("%s %s\n", e.what());
} catch(...){
printf("generic exception");
}
但这是通用的...... catch块。我知道MS特定的__try在某种程度上可能有用,但我更喜欢标准的C ++,并且无论如何我都有析构函数来阻止使用__try。
澄清:上面的代码被简化用于讨论目的。实际上,除零是一个在第三方DLL深处发生的错误,我没有源代码。错误取决于我传递给库的参数(复杂结构的句柄),但不是以任何明显的方式。所以,我希望能够优雅地恢复。
答案 0 :(得分:9)
C ++不会将除零作为例外处理。
引用Stroustrup:
“低级事件,例如算术 溢出并除以零,是 假设由专门的人处理 较低级别的机制而不是 例外。这使C ++能够匹配 当其他语言的行为 它来算术。它也避免了 严重的问题 流水线架构的事件 比如除以零 异步“。
“C ++的设计与演变”(Addison Wesley,1994)
在任何情况下,例外永远不会替代正确的前提条件处理。
答案 1 :(得分:9)
要在Visual C ++中捕获除以零的异常,请尝试使用catch(...)在项目设置中启用/ EHa选项。请参阅项目属性 - > C / C ++ - >代码生成 - >将“启用C ++例外”修改为“是和SEH例外”。就是这样!
详情请见: http://msdn.microsoft.com/en-us/library/1deeycx5(v=vs.80).aspx
答案 2 :(得分:8)
假设您无法简单地修复异常生成代码的原因(可能是因为您没有该特定库的源代码,也许是因为您无法在导致问题之前调整输入参数)
你必须跳过一些箍来让你按照自己喜欢的方式工作,但是可以做到。
首先,您需要通过调用_set_se_translator()
来安装结构化异常处理转换函数(请参阅here),然后您可以检查在发生SEH异常时传递的代码并抛出适当的C ++例外。
void CSEHException::Translator::trans_func(
unsigned int code,
EXCEPTION_POINTERS *pPointers)
{
switch (code)
{
case FLT_DIVIDE_BY_ZERO :
throw CMyFunkyDivideByZeroException(code, pPointers);
break;
}
// general C++ SEH exception for things we don't need to handle separately....
throw CSEHException(code, pPointers);
}
然后,您可以通过正常方式在C ++中捕获CMyFunkyDivideByZeroException()
。
请注意,您需要在要转换异常的每个线程上安装异常转换函数。
答案 3 :(得分:7)
您可以使用结构化异常处理(使用__try等),也可以安装结构化异常处理程序翻译器:_set_se_translator
这两个都是特定于操作系统的。
答案 4 :(得分:4)
使用标准C ++不能这样做,因为它不是标准的C ++异常。这是一个结构化的例外。对于标准C ++异常,有人必须从代码中执行throw exception;
。
答案 5 :(得分:3)
为什么不先检查一下?与异常处理的上下文切换相比,简单j == 0
的性能将是微不足道的。
答案 6 :(得分:2)
请尝试以下代码:
try
{
const int j=0;
if (j == 0) { throw std::exception("j was 0"); }
const int i= 1/j;
}
catch(std::exception& e)
{
printf("%s %s\n", e.what());
}
catch(...)
{
printf("generic exception");
}
当然,如果你没有例外地做到这一点,你可以这样做:
const int j = 0;
if (j == 0)
{
/* do something about the bad pre-condition here */
}
else
{
const int i = 1 / j;
}
编辑以回应澄清:你必须弄清楚你正在交给第三方的输入是什么导致它们在事前除以零,并在调用它们的函数之前处理它。
答案 7 :(得分:1)
一个好方法是使用像SafeInt这样的安全面向对象的包装器。它在Visual Studio 2010中也是seems to be integrated。
更新
如果在第三方代码中发生除零,则您唯一的选择是SEH或等同于answered by Seb Rose的其他选项
答案 8 :(得分:0)
您可以使用try-except Statement。 但是,不要忘记您需要为每个线程设置它。