Java и C ++ о проблеме разматывания стека - PullRequest
11 голосов
/ 31 марта 2010

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

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

Ответы [ 4 ]

10 голосов
/ 31 марта 2010

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

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

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

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

5 голосов
/ 31 марта 2010

Разматывание стека - это, в частности, вызов деструкторов всех полностью построенных объектов в цепочке вызовов вплоть до точки, где перехватывается исключение.

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

2 голосов
/ 31 марта 2010

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

2 голосов
/ 31 марта 2010

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

...