繁体   English   中英

Stack Unwinding问题上的Java和C ++

[英]Java and C++ on Stack Unwinding issue

据我所知,在未捕获异常的情况下,C ++会立即销毁局部变量,Java会释放引用并将其余部分留给垃圾收集器。

这是正确的吗? Java和C ++在这个问题上究竟有什么区别? 换句话说,就堆栈展开问题而言,这两种语言中的哪一种被认为更好? :)

我会为此受到抨击,但......

在堆栈展开前,C ++比Java更好 - 没有竞争。 C ++对象析构函数一直触发堆栈直到达到捕获点 - 沿途释放所有托管资源。

正如你所说的那样,Java将所有这些都置于非确定性垃圾收集器(最坏的情况)或者任何明确制作的最终块的手中,你已经散布了你的代码(因为Java不支持真正的RAII) 。 也就是说,所有资源管理代码都掌握在每个类的客户手中,而不是应该在类设计者手中。

也就是说,在C ++中,如果您小心确保析构函数本身不会发出异常,则堆栈展开机制只能正常运行。 一旦你有两个活动的例外,你的程序abort()没有通过go(当然也没有触发任何剩余的析构函数)。

堆栈展开专门调用调用链上的所有完全构造的对象的析构函数,直到捕获到异常的点。

Java根本没有堆栈展开 - 如果抛出异常,它对对象不做任何事情。 你必须自己处理catchfinally块中的对象。 这主要是为什么C#引入了using语句 - 它们简化了调用IDisposable.Dispose(),但同样不是C ++堆栈展开的完全替代。

你是完全正确的,C ++以相反的顺序销毁所有局部变量,因为它退出堆栈上的每个函数 - 就像你以编程方式执行return - 而不是main()

对于堆栈,请执行相同的操作:它们释放您离开的块的堆栈,但异常。 在Java中,所有原始类型(int,double等)都直接保存,此时此类型的局部变量被释放。 所有对象都通过局部变量中的引用保存,因此引用将被删除,但对象本身仍保留在堆上。 如果这是对象的最后一个引用,它们将在下一个垃圾回收中释放。 如果在C ++中是在堆上创建的对象并且局部变量保留指针,则堆上的对象不会自动释放,它们永远保留在堆上(是的,你得到一个MEMORY LEAK)。 如果已在堆栈上保存了对象,则会调用析构函数(并且可能会释放堆上的其他引用对象)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM