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

时间:2011-09-20 04:28:07

标签: java c++ 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";
}

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

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

5 个答案:

答案 0 :(得分:31)

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

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

语言概述:

最后和RAII

C ++和Java之间最重要的区别之一是Java支持finally语句。无论前面的finally块中的代码是否被执行,catch块中的代码总是运行。例如:

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

finally语句的目的是允许程序员在那时清理,即释放套接字,关闭文件句柄等......即使Java运行垃圾收集器,垃圾收集只适用于内存而不适用于其他资源。您仍然需要manually dispose of resources。现在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 (...)
  {
  }
}

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

捕获所有陈述

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

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

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

catch (...)
{

}

未处理的例外

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

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

答案 1 :(得分:8)

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


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

答案 2 :(得分:1)

实际上,您可以在C ++中捕获系统异常。有一个编译器选项(至少在Visual Studio中)可以捕获访问冲突异常(这就是程序崩溃的原因)。

Java更加谨慎,因此复杂的幻觉。

请考虑以下事项:

在Java中:

int x[10];
int i = 20;
try
{
    int k = x[i];
}
catch (ArrayIndexOutOfBoundsException ex)
{
     //will enter here
}

Int C ++:

int x[10];
int i = 20;
try
{
    if ( i >= 10 )
        throw new "Index out of bounds";
    int k = x[i];
}
catch (...)
{
    //now it will enter here
}

这一切都与您是否希望将更多内容留给运行时环境(如Java的情况)或您自己想要处理的事情有关。 C ++为您提供更多控制权,但您必须更加关注。

如果不处理异常,你的Java程序也会崩溃 - 想一想,如果一个方法明确地抛出异常,你就无法处理它,因为编译器不允许你。如果没有明确说明,除非被try / catch包围,否则程序仍会崩溃。

如果您问为什么系统异常无法在C ++中处理,我已经回答:他们可以,就是这样,默认情况下,这是关闭的。

答案 3 :(得分:1)

任何语言的例外都是或应该是处理的 例外情况。但仍然可以让你合理的情况 关于全球计划状态的假设,并可能恢复。 编程错误通常意味着您不能做任何假设 全局程序状态,并且必须尽快终止代码 可能,执行最少的额外代码(因为你不知道什么 它会这样做。

在Java中,几乎所有内容都是通过异常进行报告的。 一切都来自常见的预期错误(尝试时“找不到文件”) 打开文件)以发现严重的内部错误 (java.lang.VirtualMachineError)。 C ++为您提供了选择:如果您 检测到编码错误(断言失败),可以中止该过程 立即(通常比在未知的情况下顽固更合适 州);如果“错误”是通常会发生的事情 日常操作(“找不到文件”),您可以测试状态,或使用 返回代码(再次,通常比异常更合适)。为一个 C ++使用的两种情况之间的情况(例如,内存不足) 异常。

当然,在给定的应用程序中最合适的是: 肯定存在“未找到文件”的例外情况(例如,如果 该文件是应用程序的一部分,没有它就无法运行),和 保证例外。同样,在特定情况下,空指针可以 用于控制程序逻辑(if ( ptr == NULL ) ...)或 对应一个例外情况(if ( ptr == NULL ) throw ...);在 在其他情况下,空指针是编程错误 (assert( ptr != NULL))。

答案 4 :(得分:0)

  1. C ++和Java都尝试捕获块,但Java最终有一个新块,它总是在try和catch之后执行。
  2. Java只抛出对象,但C ++抛出数据(原始,指针和对象)。
  3. C ++有catch(...){}来捕获所有类型的异常,Java有捕获(Exception e){}来捕获所有异常。