On Friday, 12 September 2014 at 03:37:10 UTC, Jakob Ovrum wrote:
2) The above really shows how beneficial dynamic memory allocation is for exceptions. A possibility would be to allocate exceptions on a non-GC heap, like the C heap (malloc) or a thread-local heap. Of course, without further amendments the onus is then on the catch-site to explicitly manage memory, which would silently break virtually all exception-handling code really badly.

However, if we assume that most catch-sites *don't* escape references to exceptions from the caught chain, we could gracefully work around this with minimal and benevolent breakage: amend the compiler to implicitly insert a cleanup call at the end of each catch-block. The cleanup function would destroy and free the whole chain, but only if a flag indicates that the exception was allocated with this standard heap mechanism. Chains of exceptions with mixed allocation origin would have to be dealt with in some manner. If inside the catch-block, the chain is rethrown or sent in flight by a further exception, the cleanup call would simply not be reached and deferred to the next catch-site, and so on.

Escaping references to caught exceptions would be undefined behaviour. To statically enforce this doesn't happen, exception references declared in catch-blocks could be made implicitly `scope`. This depends on `scope` actually working reasonably well. This would be the only breaking change for user code, and the fix is simply making a copy of the escaped exception.

Anyway, I'm wondering what thoughts you guys have on this nascent but vitally important issue. What do we do about this?

I think option "b)" is the right direction. However, I don't think it is reasonable to have the "catch" code be responsible for the cleanup proper, as that would lead to a closed design (limited allocation possibilities).

I like the option of having "exception allocators" that can later be explicitly called in a "release all exceptions" style, or plugged into the GC, to be cleaned up automatically like any other GC allocated exception. This would make the exceptions themselves still @nogc, but the GC would have a hook to (potentially) collect them. For those that don't want that, then they can make calls to the cleanup at deterministic times.

This, combined with the fact that we used an (unshared) allocator means the cleanup itself would be 0(1).

Finally, if somebody *does* want to keep exceptions around, he would still be free to do so *provided* he re-allocates the exceptions himself using a memory scheme he chooses to use (a simple GC new, for example).



... well, either that, or have each exception carry a callback to its allocator, so that catch can do the cleanup, regardless of who did the allocation, and how. GC exceptions would have no callback, meaning a "catch" would still be @nogc. An existing code that escapes exceptions would not immediately break.

Either way, some sort of custom (no-gc) allocator seems in order here.

Reply via email to