Java и С++ по проблеме разматывания стека

Насколько я знаю, в случае неперехваченного исключения С++ немедленно уничтожает локальные переменные, Java выпускает ссылки и оставляет остальную часть сборщика мусора.

Правильно ли это? В чем разница между Java и С++ по этой проблеме? другими словами, какой из этих двух языков считается лучшим с точки зрения проблемы разворота стека?:)

Ответ 1

Я собираюсь получить пламя для этого, но...

С++ - это руки лучше, чем Java в стеке, разматывающие фронт - там просто нет конкурса. Деструкторы объектов С++ полностью уничтожают стек до тех пор, пока точка захвата не будет достигнута - изящно освободите все управляемые ресурсы по пути.

Как вы сказали, Java оставляет все это во власти не детерминированного сборщика мусора (в худшем случае) или в руках каких-либо явно созданных блоков finally, которые вы замусорили свой код (поскольку Java не поддерживает true RAII). То есть весь код управления ресурсами находится в руках клиентов каждого класса, а не в руках дизайнера классов, где он должен быть.

Тем не менее, на С++ механизм разворачивания стека функционирует нормально, если вы тщательно следите за тем, чтобы сами деструкторы не испускали исключений. После того, как у вас есть два активных исключения, ваша программа abort() без прохождения идет (и, конечно, без увольнения любого из оставшихся деструкторов).

Ответ 2

Stack unwinding специально вызывает деструкторы всех полностью сконструированных объектов в цепочке вызовов вплоть до точки, где исключение поймано.

Java просто не имеет разбиения стека - он ничего не делает для объектов, если генерируется исключение. Вы должны сами обрабатывать объекты в блоках catch и finally. В основном это потому, что С# представил using statement - они упрощают вызов IDisposable.Dispose(), но опять же, что не полная замена для стека C++.

Ответ 3

Вы совершенно правы, С++ уничтожает все локальные переменные в обратном порядке, поскольку он выходит из каждой функции в стеке - так же, как если бы вы программно выполняли возврат - и из main().

Ответ 4

Для стека оба они одинаковы: они освобождают стек для блоков, которые вы оставляете с исключением. В Java все примитивные типы (int, double и т.д.) Сохраняются напрямую, в этот момент публикуются локальные переменные этого типа. Все объекты сохраняются через ссылки в локальных переменных, поэтому ссылки удаляются, но сами объекты остаются в куче. Если это была последняя ссылка на объект, они будут выпущены в следующей сборке мусора. Если в С++ созданы объекты в куче, а локальные переменные содержат указатель, объекты в куче не будут выпущены автоматически, они останутся на куче навсегда (да, вы получите ПАМЯТЬ ПАМЯТИ). Если вы сохранили объекты в стеке, тогда деструктор вызывается (и может освобождать другие ссылочные объекты в куче).