LWN.net Logo

Uses

Uses

Posted Apr 1, 2012 2:37 UTC (Sun) by cmccabe (guest, #60281)
In reply to: Uses by Cyberax
Parent article: Go version 1 released

> C++ has a better idea - exception guarantees

You really need to get out of the mentality that C++ is a single thing that "has ideas." Even aside from the obvious anthropomorphism, there is no single person or company that controls the direction of C++. New features are added by a committee. Over the years, an amazing number of features got added. Some of them are useful, some of them are not. Some of them are useful, but interact poorly with other useful features. In the real world, companies choose the subset of features they like the best, and move on.

I programmed C++ for almost 10 years. I've seen a lot of different styles of code in that time. I was once a passionate advocate of exceptions, Boost, and design patterns. My opinions changed a lot when I saw the real-world messes these things made. Reading some of the Golang documents, I found myself agreeing with every point they made. Finally, someone with real-world experience building systems and good taste was designing a successor to C++.

> http://en.wikipedia.org/wiki/Exception_guarantees ). I rarely care about
> types of exceptions but I really care about the fact that exceptions can
> occur at all. Having a type system enforcing correct exception safety
> would be really nice.

The only "guarantees" worth the name are those that are enforced by the compiler. Calling something a "guarantee," when it may or may not be true, is an Orwellian misuse of the language-- like calling a DRM format "PlaysForSure." In my experience, only the best programmers can have even a chance of writing exception-safe code in C++. And even they make mistakes, being human.

> [snip examples]

If it's a programmer error, then panic. If it's anything else, return an appropriate result, whatever that may be.

> Exceptions help to deal with a thorny problem - non local effects
> of errors.

To do proper error handling, you need to clean up local resources. Do exceptions help with that? Nope, it's your job-- even in Java or Python. You need to decide how to handle the problem. Do exceptions help there? Nope. At the end of the day, they are no more than a "goto," whitewashed with a shiny new coat of object-oriented paint.


(Log in to post comments)

Uses

Posted Apr 1, 2012 6:41 UTC (Sun) by Cyberax (✭ supporter ✭, #52523) [Link]

Well, I know that C++ doesn't like it when people anthropomorphize it. But it's easier than saying 'some members of C++ committee'.

Golang already shows its ugly areas - people shouldn't allow C developers to design languages. And as I've said, error handling is one of the ugly parts.

I've written a fair amount of code in Go and I've already encountered cases where changes to functions required addition of 'err' parameter, breaking my code in the process.

A some libraries now have all the functions returning Error as the second parameter in all functions, even if it's never actually used but might be used some day in future. Which is crazy.

>The only "guarantees" worth the name are those that are enforced by the compiler.

And that's the plan for the next C++. Even C++11 has noexcept which is already a good step in the right direction ( http://akrzemi1.wordpress.com/2011/06/10/using-noexcept/ ).

Go instead decided to make a step back - it HAS exceptions (a rose by any other name...) but they are fugly.

>If it's a programmer error, then panic. If it's anything else, return an appropriate result, whatever that may be.

That's the result of map.get('something') if map itself misbehaves?

>To do proper error handling, you need to clean up local resources. Do exceptions help with that?

YES, THEY DO!!!

In C++ exception force you to use RAII to manage resources. That ensures that resources are automatically released during the normal execution flow and simply CAN'T be leaked.

While explicit error code handling practically ensures that some cleanup actions are going to be missed. That's why the most common error handling pattern in plain C is 'goto cleanup' which essentially emulates the stack unwinding.

Uses

Posted Apr 1, 2012 23:18 UTC (Sun) by cmccabe (guest, #60281) [Link]

> I've written a fair amount of code in Go and I've already
> encountered cases where changes to functions required
> addition of 'err' parameter, breaking my code in the process.

One of the worst APIs I've used was the original wireless.h (aka "wireless extensions") API in the Linux kernel. Basically, it forwards you a bunch of ioctls that come from userspace. Except it doesn't bother to parse them at all-- it's YOUR job to parse a giant blob of bytes, try to pick out fields, and do pointer-chasing.

When asked why this was so, the author simply replied, "if I had provided a callback API, I would have had to update all the callback implementors each time I added a new field." (I'm paraphrasing a bit; I can't find the original email.) When I read this response, I couldn't stop laughing for about a minute. Well of COURSE you have to change the callback implementors when the ioctl changes. That's the point of the type system! But he couldn't see it. Later wireless.h was replaced by the excellent nl80211 API.

I think, like him, you may be missing the point here. The point of the type system is to make guarantees. Real guarantees, not just conventions. "I will not encounter any errors" is just such a guarantee, and that's what you're promising when you don't provide an error return code.

[snip discussion of noexcept]

C++ already HAS a way of declaring that a function won't throw-- add "throw()" to the end of the function. They're going to add another way?

And apparently this new way will also just be a programmer promise with no real weight:

> This technically allowed the possibility that a noexcept function could
> still throw: this would trigger an undefined behavior. In addition,
> current exception specifications in C++03 were to be deprecated.
>
> Then, Rani Sharoni proposed a different solution... [snip]

Yeah. Sounds like progress. C++ throw specifications are FUBAR, and a change like this will just turn the pain level up to 11. You'll be dealing with two __different__ broken exception specification systems. Good luck dealing with library code that may not get updated to the new system for years!

Even if they managed to sort out this mess, they'd still just be re-inventing Java checked exceptions, which most people find verbose and annoying.

> In C++ exception force you to use RAII to manage resources. That ensures
> that resources are automatically released during the normal execution flow
> and simply CAN'T be leaked.
>
> While explicit error code handling practically ensures that some cleanup
> actions are going to be missed. That's why the most common error handling
> pattern in plain C is 'goto cleanup' which essentially emulates the stack
> unwinding.

Exceptions and RAII are two different things. For example, Google does not use exceptions, but they make heavy use of RAII. Golang also has its own version of RAII, the defer statement. And, of course, garbage collection means that there is a lot less cleanup to do.

Anyway, even Herb Sutter admits that the best exception-safe code which implements a certain algorithm may sometimes be less efficient than the best non-exception-safe code. And he's an enthusiastic advocate of exceptions. So my question to you is, if you're going to sacrifice efficiency in this way, why use a low-level, non-garbage collected, memory-unsafe language in the first place?

Uses

Posted Apr 2, 2012 14:34 UTC (Mon) by jwakely (subscriber, #60262) [Link]

C++ already HAS a way of declaring that a function won't throw-- add "throw()" to the end of the function. They're going to add another way?
A non-empty exception spec i.e. throw(X,Y,Z) is deprecated, but you're left with (as before) throw() meaning the function won't throw or if that's not given then (as before) it means the function might throw, and could throw any type.

But in order to make throw() useful for metaprogramming there's a new way to spell it which is noexcept(true) or simply noexcept. You can also say noexcept(false) to say a function might throw, which seems useless until you realise the boolean can be any constant expression, so a function template with parameter T can be declared noexcept(is_nothrow_copyable<T>::value) i.e. the function guarantees not to throw if copying T won't throw. There is also a noexcept operator that can be used to query whether arbitrary expressions will throw.

It's not a new mechanism, it's the same one with the useless part (non-empty exception specs) removed, and more useful syntax.

If library code isn't updated to the new mechanism it doesn't matter, it still works fine (but noone should be using non-empty exception specs anyway, they're crap) and throw() is equivalent to noexcept.

Uses

Posted Apr 2, 2012 15:00 UTC (Mon) by jwakely (subscriber, #60262) [Link]

(It's not _precisely_ the same, but the differences for most people's uses are equivalent or are an improvement anyway.)

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds