有没有C++的等价物来替代Java的
try {
...
}
catch (Throwable t) {
...
}
我正在尝试调试调用本地Windows函数的Java/jni代码,但虚拟机一直崩溃。本地代码在单元测试中看起来很好,只有通过jni调用时才会崩溃。一个通用的异常捕获机制将非常有用。
有没有C++的等价物来替代Java的
try {
...
}
catch (Throwable t) {
...
}
我正在尝试调试调用本地Windows函数的Java/jni代码,但虚拟机一直崩溃。本地代码在单元测试中看起来很好,只有通过jni调用时才会崩溃。一个通用的异常捕获机制将非常有用。
try{
// ...
} catch (...) {
// ...
}
可以捕获所有C++异常,但这应该被视为不好的设计。您可以使用C++11的new current_exception机制,但如果您没有使用C++11的能力(需要重写的旧代码系统),则没有命名的异常指针可用于获取消息或名称。您可能希望添加单独的catch子句来捕获各种异常,并仅在底部捕获所有异常以记录意外异常。例如:
try{
// ...
} catch (const std::exception& ex) {
// ...
} catch (const std::string& ex) {
// ...
} catch (...) {
// ...
}
有人应该补充一下,C++代码中无法捕获“崩溃”(crashes)。这些不会抛出异常,但会执行任何它们想做的事情。当您看到程序因为空指针引用导致崩溃时,这是未定义行为。没有 std::null_pointer_exception
。尝试捕获异常也无济于事。
只是万一有人正在阅读本主题并认为自己可以找出程序崩溃的原因,请使用像gdb这样的调试器。
如果需要捕获第三方库中的未知异常类型,在 catch(...)
代码块内部,可以使用以下方法反向工程实现异常类型:
#include <iostream>
#include <exception>
#include <typeinfo>
#include <stdexcept>
int main()
{
try {
throw ...; // throw something
}
catch(...)
{
std::exception_ptr p = std::current_exception();
std::clog <<(p ? p.__cxa_exception_type()->name() : "null") << std::endl;
}
return 1;
}
如果你能够使用Boost,你可以使你的异常捕获部分变得更简单(在外部),并且有潜力跨平台。
catch (...)
{
std::clog << boost::current_exception_diagnostic_information() << std::endl;
}
catch(...)
和catch(std::exception)
之间有什么区别? - Mayurint
。...
也可以捕获它。顺便说一下,你应该通过const&
来捕获异常。 - bobahp.__cxa_exception_type()->name()
不具有可移植性。实际上,我尝试了使用 clang 进行编译,但它无法通过。 - Edward Falkcatch (...)
时,catch语句的主体应该执行throw;
以重新抛出异常,例如记录日志,或者终止程序(例如std::terminate()
)。除非知道如何处理异常,否则不应尝试“处理”它。例如,在某些实现中,尝试终止线程会导致在该线程中引发异常(不是std::exception
的子类),因此需要展开线程的堆栈才能停止线程。因此,我们不应“无条件捕获所有异常”,因为可能存在意外情况。 - adentingertry {
// ...
} catch (...) {
// ...
}
请注意,catch
块中的...
是一个真正的省略号,即三个点。
然而,由于C++异常不一定是基类Exception
的子类,因此在使用这种结构时实际上没有办法看到抛出的异常变量。
catch
说明符与注释中的现有代码占位符(// ...
)区分开来,显然这不是C++语法。 - Greg Hewgill使用 C++,无法以便携的方式捕获所有异常。这是因为某些异常在 C++ 上下文中并不属于异常。这包括诸如除零错误等其他情况。虽然有方法可以绕过这个问题并使其能够在出现这些错误时抛出异常,但这很难做到,并且难以实现便携性。
如果要捕获所有 STL 异常,则可以执行以下操作:
try { ... } catch( const std::exception &e) { ... }
使用e.what()
可以返回一个const char*
,告诉您有关异常本身的更多信息。这是最像您询问的Java构造的构造。
如果某个人愚蠢到抛出不继承自std::exception
的异常,则此方法将无法帮助您。
简而言之,使用catch(...)
。但是请注意,catch(...)
应与throw;
结合使用,基本上如下:
try{
foo = new Foo;
bar = new Bar;
}
catch(...) // will catch all possible errors thrown.
{
delete foo;
delete bar;
throw; // throw the same error again to be handled somewhere else
}
这是使用catch(...)
的正确方式。
Foo
的析构函数,不是吗?我认为这就是RAII的全部意义。但是,如果您需要指向Foo
的指针而不仅仅是在堆栈上创建Foo
,那么您需要将指针包装在其他声明在堆栈上的东西中。 - reirab通过编写以下代码,可以实现此操作:
try
{
//.......
}
catch(...) // <<- catch all
{
//.......
}
但这里存在一种非常不明显的风险:在try
块中抛出的错误类型可能无法准确找到,因此只有在确定无论异常类型如何,程序都必须按照catch
块中定义的方式继续运行时,才使用此类catch
。
。
catch(...)
但这是非常危险的。在他的书中《调试Windows》中,John Robbins讲述了一个非常恶劣的错误信息被catch(...)命令掩盖的故事。你最好捕捉具体的异常。捕捉你认为try块可能会合理抛出的任何异常,但如果发生了真正意外的情况,请让代码抛出更高级别的异常。
我在这里只是想提一下:Java
try
{
...
}
catch (Exception e)
{
...
}
可能会漏掉一些异常!我以前真的遇到过这种情况,让人发疯;Exception从Throwable派生而来。所以,要想捕获所有东西,你不想catch Exceptions,而是要catch Throwable。
我知道听起来很吹毛求疵,但当你花了好几天时间试图找出代码中被try...catch(Exception e)包围的未捕获异常来自哪里时,它就会一直在你脑海中挥之不去。
catch(Exception)
可能无法捕获所有异常,您可能将其与C#混淆了... Java = catch(Thowable)
,C# = catch(Exception)
。不要混淆它们。 - Chef PharaohCoderMalfunctionError
(实际上是Java的一个真正的 Error
子类...尽管意思并不像它听起来那样)。 - reirab如果您想捕获所有异常以便创建 minidump ,那么...
有人已经在Windows上完成了这项工作。
请参阅 http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus 这篇文章,作者解释了他是如何找出如何捕获各种类型的异常,并提供了可行的代码。
以下是您可以捕获的列表:
SEH exception
terminate
unexpected
pure virtual method call
invalid parameter
new operator fault
SIGABR
SIGFPE
SIGILL
SIGINT
SIGSEGV
SIGTERM
Raised exception
C++ typed exception
使用方法: CCrashHandler ch; ch.SetProcessExceptionHandlers(); // 对于一个线程来说使用这个 ch.SetThreadExceptionHandlers(); // 每个线程都需要使用
默认情况下,这会在当前目录中创建一个迷你转储文件 (crashdump.dmp)