Java 当从构造函数中抛出未处理的异常时会发生什么

Java 当从构造函数中抛出未处理的异常时会发生什么,java,c++,memory-leaks,Java,C++,Memory Leaks,当从构造函数中抛出未处理的异常时会发生什么?对于java,C++?是否会出现内存泄漏?对于Java:控制流返回给调用方,就像从常规方法抛出异常一样。没有内存泄漏(半已构建的实例将被丢弃和垃圾回收),至少在C++中,一个未处理的异常会一直持续到它到达你的主程序(),从而关闭程序。未释放的内存将由操作系统处理 不确定这是否回答了你的问题 因此,基本上,它就像是从任何其他函数中抛出的一样。值得添加: 1) Java区分“已检查”和“未检查”异常 2) 大多数用户定义的异常都应该“检查”。这意味着,除非

当从构造函数中抛出未处理的异常时会发生什么?对于java,C++?是否会出现内存泄漏?

对于Java:控制流返回给调用方,就像从常规方法抛出异常一样。没有内存泄漏(半已构建的实例将被丢弃和垃圾回收)

,至少在C++中,一个未处理的异常会一直持续到它到达你的主程序(),从而关闭程序。未释放的内存将由操作系统处理

不确定这是否回答了你的问题

因此,基本上,它就像是从任何其他函数中抛出的一样。

值得添加:

1) Java区分“已检查”和“未检查”异常


2) 大多数用户定义的异常都应该“检查”。这意味着,除非调用链中的每个模块a)处理异常,或b)明确标记它可以“抛出”异常,否则代码甚至不会编译。是否发生内存泄漏取决于代码的编写方式。如果你写了“好”的代码,你不应该有内存泄漏。但完全有可能出现这样的情况,即出现严重错误

如果构造函数在构造函数中分配了任何内容,那么事情很可能会出错

通常,解决方案是使用所谓的“两阶段构造”,因此构造函数本身非常简单,“不会出错”。一旦构建了对象,您就可以调用一个成员函数,该函数以可能失败的方式填充对象,然后您可以随意抛出异常,只要确保析构函数在该行的某个点运行,所有这些都应该运行良好。当心“析构函数中的部分构造对象”tho——如果指针为空,或者在析构函数中没有部分构造其他对象,会发生什么情况

[以上内容受制于“在我们返回main之前,在某个地方有一个处理程序,我们确实想做一些事情,而不是中止整个程序”]

你问

“当一个未处理的异常从构造函数中抛出时发生了什么?对于java,C++?会有内存泄漏吗?”

未处理的异常是没有关联处理程序的异常

在C++中,任何未处理的异常都会终止程序。在这种情况下,未指定堆栈是否展开,即成功构造的局部变量的析构函数是否可以执行,这取决于编译器。从何处抛出异常(例如在构造函数内部)与此无关

C++11§15.3/9
如果找不到匹配的处理程序,则调用函数
std::terminate()
;在调用
std::terminate()
之前,堆栈是否已展开,由实现定义

Java中未处理的异常也必然终止程序,或者至少终止当前线程(如果它不是主线程),但保证调用
finally
子句:

Java SE 7语言规范§11.3
如果找不到可处理异常的
catch
子句,则终止当前线程(遇到异常的线程)。在终止之前,所有
最后执行
子句[…]”

由于程序终止,实际上程序本身没有内存泄漏,因为实际上操作系统会在进程结束后进行清理


但是,崩溃程序可能会在磁盘上留下临时文件,并且可能会泄漏服务器进程中的其他资源,包括服务器进程中的内存泄漏。C++的

< P>,答案是在C++ FAQ中。


<> P/>更多的信息,在两种语言中,情况相似,但不同的是C++或java。 当抛出异常时,它会传播回堆栈,寻找处理程序。在C++或java中,它可能永远找不到一个,从而在开始时解开所有的程序,并终止程序。在Java中,有一个已检查异常的概念,它强制执行对异常的某种处理(如果已检查)。在C++中,有一个异常规范的概念,但是它是不实用的(不设计的),不应该使用,所以,将所有异常视为C++中的“未检查”。p> 无论异常最终是终止程序还是被捕获在抛出异常的上游某个地方,导致异常的解除过程才是最重要的。如果它最终终止了程序,那么,当然,当操作系统回收内存时,不会出现内存泄漏。你需要担心的是:

  • 如果异常最终在上游某处处理,则在展开过程中内存泄漏;以及
  • 其他类型的资源可能会泄漏(例如,挂起的数据库操作、网络连接等),因为如果程序终止,操作系统不会回收/撤消这些资源

由于堆栈展开,在C++中,简单地说,每个被完全构造的堆栈绑定对象(包括正在构建的对象的数据成员或基类实例)将被立即(即确定性地)以它们创建的确切相反顺序销毁。因此,只要所有资源直接与对象(也称为“RAII”)的构造/销毁相关联,在展开过程中就不会发生(内存或其他资源)泄漏,因为成功获取的所有资源都将被释放(除非在展开过程中释放资源失败,这是您需要小心处理的事情)

在Java中,“堆栈”展开以相同的方式发生,不同的是它们没有立即销毁对象,而是被标记为丢弃(即被垃圾收集),并且