Drawbacks of exceptions being globally allocated

Tejas notrealemail at gmail.com
Sun Aug 15 18:47:27 UTC 2021


On Sunday, 15 August 2021 at 16:23:25 UTC, Ali Çehreli wrote:
> On 8/15/21 2:10 AM, Alexandru Ermicioi wrote:
>
> >> This may be useful in some cases but in general, these
> colatteral
> >> exceptions don't carry much information and I don't think
> anybody
> >> looks at them. Usually, the first one is the one that
> explains the
> >> error case.
>
> > That is just an assumption.
>
> Agreed but it's based on hands-on experience as well as 
> exposure to these forums. :)
>
> > There could be designs where original
> > exception gets wrapped in another one
>
> Wrapping is different and yes, it is useful. There have been 
> cases where I hit a ConvException which only tells me a 
> conversion failed. I do catch and augment it in outer contexts 
> to saying something similar ot "That happened while doing this".
>
> > Regarding exception chaining, do you mean that it will
> automatically get
> > chained, even without explicitly passing it as constructor of
> wrapping
> > exception?
>
> Yes. That's the functionality which isn't very useful because 
> the collateral exceptions are usually because of the main one: 
> Imagine the file system is full and a destructor cannot flush a 
> file. The destructor's error is not interesting in this case.
>
> class Main : Exception {
>   this() {
>     super("Main failed");
>   }
> }
>
> class Dtor : Exception {
>   this() {
>     super("The destructor failed");
>   }
> }
>
> struct S {
>   ~this() {
>     throw new Dtor();
>   }
> }
>
> import std.stdio;
>
> void main() {
>   try {
>     auto s = S();
>     throw new Main();
>
>   } catch (Exception exc) {
>     stderr.writeln("Failed: ", exc.msg);
>     stderr.writeln("This failed too: ", exc.next.msg);
>     // (Of course, real code should stop when 'next' is null.)
>   }
> }
>
> That output contains two automatically chained exceptions:
>
> Failed: Main failed
> This failed too: The destructor failed
>
> Ali

Do you see anything wrong with the following `emplace`-allocated, 
RAII following exceptions:

```d
import std;
import core.stdc.stdlib;

class Main : Exception {
   this() @nogc{
     super("Main Failed");
   }
}

class Dtor : Exception {
   this() @nogc{
     super("The destructor failed");
   }
}

T heapAllocate(T, Args...)(Args args)@nogc{
     auto size = __traits(classInstanceSize, T);
     auto memory = malloc(size)[0 .. size];
     auto instance = emplace!(T,Args)(memory, args);
     return instance;
}

struct S {
   ~this()@nogc {
     scope a = heapAllocate!Dtor();
     throw a;
   }
}

void main() @nogc{
   try {
     auto s = S();
     scope a = heapAllocate!Main();
     throw a;

   } catch (Exception exc) {
     printf("Failed: %s\n", cast(char*)exc.msg);
     printf("This failed too: %s\n", cast(char*)exc.next.msg);
     // (Of course, real code should stop when 'next' is null.)
   }
}

```

Is this good enough for general use now? Any other drawbacks?


More information about the Digitalmars-d-learn mailing list