2011-10-21 63 views
1

我有一个C++应用程序内置MS Visual Studio 2005链接到第三方库。对于某个输入,应用程序在第三方库中崩溃(显然在realloc.c中的某处;因此必须是某种内存问题)。我在发布中运行,因为输入是巨大的。所以我跑了,直到它崩溃,然后选择调试。当我单独调试有罪功能时,我希望使用一些异常处理来防止应用程序崩溃,而不是干脆地退出。所以我用了类似的东西:MS Visual Studio 2005 C++异常处理

try { 
    //- call 3rd party application function that fails 
} 
catch(...) { 
    //- handle exception or whatever 
    Logger::Fatal("Fatal error: Exiting..."); 
    return false; 
} 

但令我惊讶的是,应用程序仍然崩溃!我期待看到它显示错误消息,因为我大概已经用省略号(...)捕获了所有异常;我在这里错过了什么?我甚至尝试在项目属性 - > C/C++ - >代码配置 - >启用异常处理中设置/ EHca(was/EHsc)。在有关可能导致问题的相关说明中,以下用法是否正确?

my_class* mc[] = {nil, nil, nil}; 
for (int i = 0; i < 3; ++i) { 
    mc[i] = new my_class(); 
    //-Do stuff with mc[i] 
    if (mc[i] != nil) { 
     delete mc[i]; 
     mc[i] = nil; 
    } 
} 

未能获取异常处理工作是相当令人费解。我当然会欣赏C++大师们的想法/见解。顺便说一句,同样的问题也发生在Linux(RHEL5),但我目前正试图让异常处理在Windows上工作。

注:当我让它调试后坠毁。我确实收到“访问冲突......无法读取位置”消息。有了这个更新的信息,我希望在C++中的某些东西仍然可以在Windows上运行,用于这种崩溃的Linux操作系统。

+1

好像你期待一个'C'功能在这里抛出异常。 –

+0

嗯...它可能的第三方应用程序调用C函数是有罪的。但是,你的意思是不行吗?那么我怎么能从C++中处理这些异常? –

+0

除非你知道抛出了一个异常,你怎么能捕捉到它呢?也许第三方库只是崩溃而不会抛出任何异常。您需要确保第三方库发出异常。 –

回答

1

您是否尝试过通过调用SetUnhandledExceptionFilter捕捉崩溃?

+0

谢谢@Miguel。是否有任何标准处理程序可以在Linux上运行?由于这看起来是MS Visual Studio特定的。 –

+1

我给你的是一个OS级异常处理程序,它与C或C++或Visual Studio无关。不知道它是否会起作用,但可能会起作用。是的,它只是Windows。我建议您不要尝试解决在应用程序中看似严重的问题,而是花一些时间调试和修复内存问题。在Linux上,我确信Valgrind可以提供帮助。 – Miguel

+0

谢谢@Miguel。当然,我会调试它..但由于它发生在第三方应用程序,我正在寻找提交异常处理程序,以便它不会在用户调试时遇到用户崩溃。 –

0

由于米格尔建议,以解决您的问题以正确的方式可能是使用SetUnhandledExceptionFilter。但我想详细解释你的现象。

首先,并不是所有的程序“崩溃”都涉及到异常。例如,CRT可能在错误时触发程序终止,例如vector中的无效元素访问或纯虚拟析构函数调用。如果你想覆盖的情况下,以及 - 见set_unexpectedset_terminate

除了这一点,catch块仅可赶上从适当的代码块抛出的异常。 OTOH有可能是在其他地方调用的函数,比如窗口的程序(如适用),其他线程等

现在,关于你的问题。我们首先要明白为什么像catch(...)这样的东西可能会遇到访问冲突等问题,以及为什么这并不总是会发生(就像你的情况一样)。

Windows提供了自己的异常处理机制 - SEH,结构化异常处理。它远远优于C++异常处理。此外,硬件中断(由CPU引起)会自动“转换”为SEH异常,因此使用SEH的代码可处理软件异常和硬件故障。

Microsoft C++编译器实际上通过SEH实现了C++异常。也就是说throw经由RaiseException实现与指定C++ - 专用的异常代码和参数,catch是一个C++ - 用于__except特定包装,以及用于与析构函数的每个对象的编译器生成类似于__finally块的东西。反之亦然。当引发非C++异常时 - 执行为C++异常生成的相同代码。

此外还有一些同时影响编译器的异常处理代码生成,它在运行时的行为所谓的编译器的异常处理选项。他们被称为异常处理模型:

  • 同步。编译器生成的代码只有在明确提出异常时才能保证正常工作。这包括throw statments,所有的“洋”的功能,其代码是不编译器(在一些变化 - 只有C++外国功能)可见。特别是从记忆中读取被认为是“安全的”。
  • 异步。编译器不允许假设任何有关可能出现异常的地方。因此,即使存取地址发生异常,它也会生成应该正常工作的代码。

此外,这是一个在catch (...)故意调用CRT代码忽略非C++异常,除非异步EH模型choosen

所以,如果你想catch (...)赶上非C++异常 - 你必须选择异步EH模型。

有一次,我写了一个article on the codeproject,之后我在驱动程序的开发相关的问题。它详细解释了这一切。