Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Except that exceptions and non-garbage collected languages don't work that well toguether.


I'll have to admit I'm not very familiar with such languages, but shouldn't finally clauses and RAII be sufficient to deal with any necessary cleanup?


Exceptions disrupt the program flow at any place, including constructors and destructors.

It's not easy to guarantee that you deallocate on destructors exactly the resources that were allocated at the constructor when both of them can stop their execution at any time. Finally clauses are technically enough, but each allocation needs the same level of attention non-memory resources (e.g. connections, files) get on other languages.


I'm going to answer for C++, since as far as I know it's the only major language with exceptions and RAII. Correct me if I'm misunderstanding your post.

> It's not easy to guarantee that you deallocate on destructors exactly the resources that were allocated at the constructor when both of them can stop their execution at any time.

I disagree; let's take this one case at time to keep it simple:

1. Destructors: within C++, if you're in a destructor, the object was fully constructed, and thus you know the exact set of resources requiring destruction. It is idiomatic C++ that a destructor should not throw; I'll discuss why below.

2. Constructors: these certainly can throw at any moment, as resource acquisition is often fraught with failures. That said, idiomatic C++ provides mechanisms (RAII, such as std::unique_ptr) to manage the partially constructed set of resources in a constructor, such that if something goes wrong, they will be automatically released by virtue of the variable going out of scope. Once you have the resource acquisition completed, you transfer ownership of the objects to the object you're constructing, which is practically guaranteed to be exception-free, since it's usually just moving a pointer under the hood.

> Finally clauses are technically enough

I don't really think you can both stand by the fact that destructors can throw at any moment and that finally clauses are enough, without making what amounts to an apples to oranges comparison. Take, for example, this function, where we assume releasing a resource can fail:

  Foo() {
    SomeResource resource;
    // Assume the destruction of a SomeResource can fail.
    // Other actions take place, some of which may raise/throw.
  }
In this example, if the other actions throw an exception that causes Foo to itself abort, then SomeResource resource must be destructed. If we're assuming that destructor can also throw, we've now got two exceptions, and how do you handle two exceptions? (It's language dependent. Some discard an exception, some chain them, some, like C++, just terminate.)

If we translate this to using some sort of "finally" construct, say in a garbage collected language:

  def foo():
    resource = aquire_some_resource()
    try:
      # other actions that may raise/throw.
    finally:
      resource.release()  # but we're assuming this can also raise/throw.
You still have the same problem at the resource.release(): up to two exceptions can occur at a given point in the program, and you then need to know what your language does in that situation.

The general gist of this is that if the "release" of some generic resource can fail, then you have to make harder decisions about what happens during a stack unwind due to some other error because now you have two errors. Do you ignore it? Log it? (can you log it?)

If releasing a resource cannot fail, destructors (and finally clauses in languages lacking RAII-style resource management) cannot fail.


"It is idiomatic C++ that a destructor should not throw;...which is practically guaranteed to be exception-free..."

"Should not", "practically". Your confidence is overwhelming. :-)

Exception safety in C++ may not be quite as much of a black art as it once was (say, before std::unique_ptr), but it is still something the programmer has to do, actively.

"If releasing a resource cannot fail, destructors (and finally clauses in languages lacking RAII-style resource management) cannot fail."

Yupper.

I'm probably unqualified to have an opinion on this, but I believe that the entire hatred for checked exceptions in Java comes from that general piece of idiocy and specifically from JDBC's urge to possibly throw a SQLException from close(). (Just what the hell is anyone supposed to do with that?)


For a long time, Java suffered from issues when throwing an exception during stack unwind. The second exception is the one that is subsequently propagated, and in modern Java the original exception is available and printed in any stack trace.

It's still not particularly pleasant, but it is at least survivable and no information is lost.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: