Live data from Hacker News

C++ says “We have try... finally at home”

devblogs.microsoft.com

131–140 of 152 posts

Re: C++ says “We have try... finally at home”

#131
post #74

> In Java, Python, JavaScript, and C# an exception thrown from a finally block overwrites the original exception, and the original exception is lost. Pet peeve of mine: all these languages got it wrong. (And C++ got it extra-wrong.) The error you want to log or report to the user is almost certainly the original exception, not the one from the finally block. The error from the finally block is probably a side effect…

This part is not correct. I can't speak for the other languages, but in Python the exception that is originally thrown is the one that creates the traceback. If the finally block also throws an exception, then the traceback includes that as additional information. The author includes an addendum, yet he is still wrong about which exception is first raised.

I believe this might be slightly imprecise also.

The traceback is actually shown based on the last-thrown exception (that thrown from the finally in this example), but includes the previous "chained exceptions" and prints them first. From CPython docs [1]:

> When raising a new exception while another exception is already being handled, the new exception’s __context__ attribute is automatically set to the handled exception. An exception may be handled when an except or finally clause, or a with statement, is used. [...] The default traceback display code shows these chained exceptions in addition to the traceback for the exception itself. [...] In either case, the exception itself is always shown after any chained exceptions so that the final line of the traceback always shows the last exception that was raised.

So, in practice, you will see both tracebacks. However, if you, say, just catch the exception with a generic "except Exception" or whatever and log it without "__context__", you will miss the firstly thrown exception.

[1]: https://docs.python.org/3.14/library/exceptions.html#excepti...

Re: C++ says “We have try... finally at home”

#132

Calling arbitrary callbacks from a destructor is a bad idea. Sooner or later someone will violate the requirement about exceptions, and your program will be terminated immediately. So I'd only use this pattern in -fno-exceptions projects. In a similar vein, care must be taken when calling arbitrary callbacks while iterating a data structure - because the callback may well change the data structure being iterated (cla…

Throwing exceptions in destructors in C++ is fine, as long as your code is exception safe.

What exactly are you referring to?

Re: C++ says “We have try... finally at home”

#133

Earlier quoted context omitted.

Python has that too, it's called a context manager, basically the same thing as C++ RAII. You can argue that RAII is more elegant, because it doesn't add one mandatory indentation level.

It's not the same thing at all because you have to remember to use the context manager, while in C++ the user doesn't need to write any extra code to use the destructor, it just happens automatically.

To be fair, that's just an artifact Python's chosen design. A different language could make it so that acquiring the object whose context is being managed could require one to use the context manager. For example, in Python terms, imagine if `with open("foo") as f:` was the only way to call `open`, and gave an error if you just called it on its own.

Re: C++ says “We have try... finally at home”

#134
post #98

Earlier quoted context omitted.

Presumably nobody informed the mods (before i did) and it was very early in the morning in the US (assuming mods are based in the US). That would explain the delay. Anyway, going forward, if anything like this happens again folks should simply shoot an email immediately to the mods and if the topic is really interesting deserving of more discussion they can always request the mods to keep the post on the frontpage fo…

It would be easier for everyone involved, and not depend on mods being awake, if HN didn't just automatically drastically change the meaning of headlines. Again, this post was misrepresenting Raymond's words for over 7 hours. That's most of its time on the front page. The current system doesn't work.

You are making mountains out of molehills.

This is the first time i have seen the auto-editorializing algorithm make a mess of the semantic meaning of a sentence which is certainly unfortunate. In most other cases (which are quite rare btw) it is generally much more benign. I presume the mods will be taking another look at their algorithm.

However, given the ways people try to influence the content on HN via title, language, brigading etc. it is good that the algorithm be strict rather than loose to prevent casual gaming of the system. And it works quite well contrary to your claim.

Re: C++ says “We have try... finally at home”

#135

I always wonder whether C++ syntax ever becomes readable when you sink more time into it, and if so - how much brain rewiring we would observe on a functional MRI.

It does get easy to read, but then you unlock a deeper level of misery which is trying to work out the semantics. Stuff like implicit type conversions, remembering the rule of 3 or 5 to avoid your std::moves secretly becoming a copy, unwittingly breaking code because you added a template specialization that matches more than you realized, and a million others.

This is correct - it does get easy to read but you are constantly considering the above semantics, often needing to check reference or compiler explorer to confirm.

Unless you are many of my coworkers, then you blissfully never think about those things, and have Cursor reply for you when asked about them (-:

Re: C++ says “We have try... finally at home”

#136
post #90

In other words: Footgun #17421 Exhibit A.

What the blog doesn't mention is how try finally can mess up your control flow. In Java the following is perfectly valid: try { throw new IllegalStateException("Critical error"); } finally { return "Move along, nothing to see here"; }

Why is this a footgun? This seems no different than using a try/catch.

try { throw new IllegalStateException("Critical error"); } catch(Exception) { return "Move along, nothing to see here"; }

Re: C++ says “We have try... finally at home”

#137

Destructors are vastly superior to the finally keyword because they only require us to remember a single time to release resources (in the destructor) as opposed to every finally clause. For example, a file always closes itself when it goes out of scope instead of having to be explicitly closed by the person who opened the file. Syntax is also less cluttered with less indentation, especially when multiple objects are…

The scope guard statement is even better!

https://dlang.org/articles/exception-safe.html

https://dlang.org/spec/statement.html#ScopeGuardStatement

Yes, D also has destructors.

Re: C++ says “We have try... finally at home”

#138
post #107

Earlier quoted context omitted.

> I don't view finalizers and destructors as different concepts. They are fundamentally different concepts. See Destructors, Finalizers, and Synchronization by Hans Boehm - https://dl.acm.org/doi/10.1145/604131.604153

It would suffice to say I don't always agree with even some of the best in the field, and they don't always agree with each other, either. Anders Hejlsberg isn't exactly a random n00b when it comes to programming language design and still called the C# equivalent a "destructor", though it is now known as a finalizer in line with other programming languages. They are things that clean up resources at the end of the li…

They are related but fundamentally different. It is a vital semantic difference (influencing the programming model itself) since destructors (C++ style) are synchronous and deterministic while finalizers (Java style) are asynchronous and non-deterministic.

It is because of all the problems that the finalize method was deprecated in Java 9 and marked "deprecated for removal"(JEP 421) in Java 18. More details at https://stackoverflow.com/questions/56139760/why-is-the-fina... and https://inside.java/2022/01/12/podcast-021/

PS: JEP 421: Deprecate Finalization for Removal - https://openjdk.org/jeps/421 Also details alternative features/techniques to use.

Re: C++ says “We have try... finally at home”

#139
post #107

Earlier quoted context omitted.

It would suffice to say I don't always agree with even some of the best in the field, and they don't always agree with each other, either. Anders Hejlsberg isn't exactly a random n00b when it comes to programming language design and still called the C# equivalent a "destructor", though it is now known as a finalizer in line with other programming languages. They are things that clean up resources at the end of the li…

They are related but fundamentally different. It is a vital semantic difference (influencing the programming model itself) since destructors (C++ style) are synchronous and deterministic while finalizers (Java style) are asynchronous and non-deterministic. It is because of all the problems that the finalize method was deprecated in Java 9 and marked "deprecated for removal"(JEP 421) in Java 18. More details at https:…

I grasp the entirety of why people differentiate "finalizers" from "destructors", but in my opinion, the practical differences in their application are not the result of the concept itself being fundamentally different, it's a result of object lifetimes being different between GC'd and non-GC'd languages. In my opinion, the concept itself is pretty close to identical. You want to clean up resources at the end of the lifetime of an object. And yes, it's practically a mess because the object lifetime ends at a non-deterministic point in the future and usually not even necessarily on the same thread. Being a big fan of Go and having had to occasionally make use of finalizers for lack of a better option in some limited scenarios, I really genuinely do grasp this, but I dispute that it has anything to do with whether or not a language has try...finally, anymore than it has anything to do with a language having any other convenient structured control flow measures, like pattern matching or else blocks on for loops.

(I do also realize that finalizer behavior in some languages is weird, for performance reasons and sometimes just legacy reasons. Go is one such language.)

But I think we've both hit a level of digression that wouldn't be helpful even if we were disagreeing about the facts (which I don't really think we are. I think this is entirely about frames of reference rather than a material dispute over the facts.) Forgetting whether finalizers are truly a form of destructor or not, the point I was trying to make really was that I don't view RAII/scoped destructors as being equivalent or alternatives to things like `finally` blocks or `defer` statements. In C++ you basically use scope guards for everything because they are the only option, but I think C++ would still ultimately benefit from at least having `finally`. You can kind of emulate it, but not 100%: `finally` blocks are outside of the scope of the exception and can throw a new exception, unlike a destructor in an exception frame. Having more options in structured control flow can sometimes add complexity for little gain, but `finally` can genuinely be useful sometimes. (Though I ultimately still prefer errors being passed around as value types, like with std::expected, rather than exception handling blocks.)

I believe the reason why we don't have languages (that I can think of) that demonstrate this exact combination is specifically because try/catch exception blocks fell out of favor at the same time that new compiled/"low-level" programming languages started picking up steam. A lot of new programming language designs that do use explicit lifetimes (Zig, Rust, etc.) simply don't have try...catch style exception blocks in the first place, if they even have anything that resemble exceptions. Even a lot of new garbage collected languages don't use try...catch exceptions, like of course Go.

Now honestly I could've made a better attempt at conveying my position earlier in this thread, but I'm gonna be honest, once I realized I struck a nerve with some people I became pretty unmotivated to bother, sometimes I'm just not in the mood to try to win over the crowd and would rather just let them bury me, at least until the thread died down a bit.

Re: C++ says “We have try... finally at home”

#140

Destructors are vastly superior to the finally keyword because they only require us to remember a single time to release resources (in the destructor) as opposed to every finally clause. For example, a file always closes itself when it goes out of scope instead of having to be explicitly closed by the person who opened the file. Syntax is also less cluttered with less indentation, especially when multiple objects are…

The scope guard statement is even better! https://dlang.org/articles/exception-safe.html https://dlang.org/spec/statement.html#ScopeGuardStatement Yes, D also has destructors.

Scope guards are neat, particularly since D has had them since 2006! (https://forum.dlang.org/thread/dtr2fg$2vqr$4@digitaldaemon.c...) But they are syntactically confusing since they look like a function invocations with some kind of aliased magic-value passed in.
Post reply on HN