C++和Java中的异常处理之间的区别?

2022-09-01 20:31:30

在 Java 中,如果特定代码行导致程序崩溃,则会捕获异常并继续执行。

但是,C++,如果我有一段导致程序崩溃的代码,例如:

try
{
    int x = 6;
    int *p = NULL;
    p = reinterpret_cast<int*>(x);

    *p = 10; // the program crashed here

    cout << "x = " << *p << endl;
}
catch(const char* Message)
{
    cout << "There is an run-time error";
}

然后程序仍然崩溃,并且未捕获异常。

那么,C++中的异常处理有什么意义呢?我是不是误会了什么?


答案 1

崩溃的行正在取消引用无效指针。在C++这不会引发异常。相反,它是未定义的行为。

C++中没有空指针异常这样的事情,这与Java不同,Java会引发空指针异常。相反,取消引用无效指针将导致未定义的行为。未定义的行为并不总是意味着崩溃,但是如果它崩溃了,你很幸运。

语言概述:

最后和 RAII

C++和Java之间最重要的区别之一是Java支持语句。无论是否执行前一个块中的代码,始终运行块中的代码。例如:finallyfinallycatch

try
{
}
catch (SomeException e)
{
}
finally
{
  //code here is always exectued.
}

finally 语句的目的是允许程序员在此时进行清理,即释放套接字、关闭文件句柄等。即使 Java 运行垃圾回收器,垃圾回收也只适用于内存,而不适用于其他资源。在某些情况下,您仍然需要手动处置资源。现在C++没有声明,所以建议该语言的用户遵守RAII原则(资源获取是初始化)Stroustrup在这里有一个关于它的解释:http://www.stroustrup.com/bs_faq2.html#finally。我更喜欢调用它,但基本上当你的对象超出范围时,调用析构函数,那么该析构函数应该释放对象维护的任何资源。finallyResource destruction is deallocation

例如,C++11x 提供了一个 std::unique_ptr 来管理以下内容:

void foo()
{
  std::unique_ptr<T> t(new T)
  try
  {
    //code that uses t
  }
  catch (...)
  {
  }
}

当函数结束时,通过 分配的资源将被删除。new

捕获所有语句

因为 Java 中的所有异常都继承自公共基类,如果您希望 catch 子句捕获任何异常,请按如下方式进行设置:Exception

catch (Exception e)
{
  //any exception thrown will land here.
}

在C++中,对可以引发的内容没有限制,并且所有异常都没有公共基类。标准做法是通过从 std::exception 继承来形成自定义异常类,但语言不强制这样做。相反,有一种特殊的语法用于捕获所有异常:

catch (...)
{

}

未处理的异常

这是语言行为不同的另一个领域。在C++未捕获的抛出异常将调用 std::terminate。std::terminate 的默认行为是调用 abort,这会生成一个 SIGABRT 并且整个程序都会停止。

在 Java 中,行为是打印堆栈跟踪并终止发生未捕获异常的线程。但是,由于 Java 程序员可能提供 UncaughtException 处理程序,因此该行为很可能与终止线程的默认值完全不同。


答案 2

并非所有崩溃都是由于未处理的异常造成的。对于您的示例,C++标准表示取消引用 NULL 指针会导致未定义的行为。在 Windows 中,您可以使用结构化异常处理 (SEH) 处理C++异常来处理使程序崩溃的问题://。在Unix中,您可以设置特殊的信号处理程序。__try__except__finally


此外,您的代码中存在错误。仅当引发此类型的异常时,才会调用 的异常处理程序。对于标准异常,您应该捕获或它是适当的子类。要捕获任何C++异常,请使用 。const char *std::exceptioncatch (...)


推荐