Hacker News new | ask | show | jobs
by MaxBarraclough 2031 days ago
> Assume that every statement can fail, and use some form RAII to manage resource cleanup.

I think that's part of Chen's point: programmers just aren't good at doing this, they even get it wrong in published code samples. Exception-handling tends to become an afterthought, and even if you do pay attention to it, it's hard to get right.

Chen is hardly alone in his scepticism. Exceptions are forbidden in the Google C++ style guide. They're also forbidden in certain critical-systems subsets of languages. Ravenscar Ada forbids exceptions, [0] as does Spark Ada (though in that case it's for a slightly different reason: it's difficult to formally reason about exceptions). edit Apparently the JSF C++ standard forbids exceptions, but MISRA C++ permits them provided certain guidelines are followed.

I agree that RAII is very useful for robust exception-handling.

> APIs can be organized to essentially force the use of RAII, even if popular but ancient APIs like POSIX file system are not designed that way

Right, this is just the kind of thing C++ wrappers add (when wrapping C APIs).

> Java/C# mechanism for running cleanup code 'try {} finally {}' a. fails to pass through a handle to the resource that needs cleanup

Short of proper RAII (destructors), I'm not sure what that would look like.

I'm not sure what Chen makes of destructors. They're non-local flow-control, but he seems to like them.

Somewhat related: Zig's optional types, which essentially force the programmer to explicitly handle the case where the data doesn't exist. [1] Much more robust than the approach C takes, where the programmer is trusted to perform the check when necessary.

[0] p20 of PDF: https://www.sigada.org/ada_letters/jun2004/ravenscar_article...

[1] https://ziglang.org/documentation/master/#Optionals

1 comments

RAII can be decoupled from ctor/dtor mechanism, see Python's 'with' statement. Javaish pseudocode, similar to a 'for' loop:

    // on exit the finally fn will be called with 'x' as an argument.
    with (Type x: create(args); finally (Type x) -> cleanup(x)) {
      // safely use x, throw at will.
    }
Re C++ and exceptions, there is an additional layer of wrinkles: throwing exceptions from ctors or, worse, dtors. Herb Sutter used to have a loooong list of what can go wrong in such situations back in the day. Explicit error codes happen to make it impossible to write ctors / dtors that can enter an error state by virtue of the fact that there is no way to return the error. My suspicion is that this is 50% of the reason of banning C++ exceptions in solid C++ style guides.
> RAII can be decoupled from ctor/dtor mechanism, see Python's 'with' statement

That may be a useful language feature, but I don't count that as full RAII. I'm inclined to agree with Wikipedia's definition that the destructor must run whenever the object's lifetime ends, to count as proper RAII:

> resource deallocation (release) is done during object destruction (specifically finalization), by the destructor

As x can presumably leak from the with block of your example, it isn't full RAII. I think it's equivalent to the confusingly named using feature of C#. [0]

> throwing exceptions from ctors or, worse, dtors. Herb Sutter used to have a loooong list of what can go wrong in such situations

Thanks for the pointer ( or should that be reference? :-P ), these are an interesting read. [1][2][3]

> Explicit error codes happen to make it impossible to write ctors / dtors that can enter an error state by virtue of the fact that there is no way to return the error

Yes, but this approach detracts from the RAII somewhat, as it means the programmer must move the substantial code out of the constructor and into a post-construction initialization member-function capable of throwing. That may be a price worth paying, but I do consider it a price, as we've lost a useful invariant: we must now keep track of which instances are in the constructed-but-unready state. An unfortunate slide back toward C.

> My suspicion is that this is 50% of the reason of banning C++ exceptions in solid C++ style guides.

I suspect these weird edge-cases where intuition diverges from reality, are much of the motivation for those prohibitions, yes.

[0] https://docs.microsoft.com/en-us/dotnet/csharp/language-refe...

[1] http://www.gotw.ca/gotw/047.htm

[2] http://www.gotw.ca/gotw/066.htm

[3] (Rather more basic) https://herbsutter.com/2008/07/25/constructor-exceptions-in-...