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

ipk*_*iss 23 c++ java exception-handling

在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";
}
Run Code Online (Sandbox Code Playgroud)

然后程序仍然崩溃,并且没有捕获异常.

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

sas*_*ang 31

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

在C++中没有空指针异常这样的东西,不像Java会抛出空指针异常.而取消引用无效指针将导致未定义的行为.未定义的行为并不总是意味着崩溃,但如果它崩溃你很幸运.

语言概述:

最后和RAII

C++和Java之间最重要的区别之一是Java支持一个finally语句.在代码finally块总是无论是否与前一代码的运行catch时执行块或没有.例如:

try
{
}
catch (SomeException e)
{
}
finally
{
  //code here is always exectued.
}
Run Code Online (Sandbox Code Playgroud)

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

例如,C++ 11x提供了一个std :: unique_ptr来管理它:

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

new当函数结束时,将删除分配的资源.

抓住所有陈述

因为Exception如果希望catch子句捕获任何异常,Java中的所有异常都从公共基类继承,那么将其设置如下:

catch (Exception e)
{
  //any exception thrown will land here.
}
Run Code Online (Sandbox Code Playgroud)

在C++中,对于可以抛出的内容没有限制,并且没有针对所有异常的公共基类.标准做法是通过继承std :: exception来形成自定义异常类,但该语言不强制执行此操作.相反,有一种特殊的语法来捕获所有异常:

catch (...)
{

}
Run Code Online (Sandbox Code Playgroud)

未处理的例外情况

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

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

  • "C++最终没有,所以建议用户使用RAII" - >"Java没有析构函数,因此他们必须在各处编写`finally`".`finally`是一种手动插入各种析构函数的形式.在最好的情况下会导致代码重复,如果您错过了案例,则会泄漏资源. (4认同)
  • @MSalters:一切都有时间和地点.虽然"finally"的所有用法都可以表示为在块的开头创建对象,其目的是在块退出时运行"finally"代码,但是在很多情况下为此目的创建包装器对象可能不那么简单,只需将适当的代码放在"finally"块中. (3认同)

Don*_*eba 8

并非所有崩溃都是由未处理的异常引起的.对于您的示例,C++标准说取消引用NULL指针会导致未定义的行为.在Windows中,您可以处理导致程序崩溃的问题,而不会抛出带有结构化异常处理(SEH)的C++异常:__try/ __except/ __finally.在Unix中,您可以设置特殊的信号处理程序.


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