Andrew Venikov:
I would rather say that the main exception should be thrown no matter what. As I described in my previous post, the main, or original exception, indicates an error in the main system/logic. The exception thrown while trying to construct an error description is just that - an error to create additional description about an already occurred error.
An exception should never indicate a logic error, because logic errors should never occur (and when they do, they are generally not recoverable.) It is not clear to me why you insist that the second exception has nothing to do with "the main system". If the main system is out of memory, it is out of memory. It cannot just be out of memory for some secondary tasks as creating an error description. In the general case, I'd argue that the second exception should be treated as more critical than the first, because the first exception can well happen in a context where it's normal for something to fail, whereas the second occurs in a context where it's not normal for something to fail (namely, the error handling branch).
It looks like we really have to decide, what's more important - preserving the original exception or preserving a newer exception. I'm trying to understand whether this dilemma simply presents a matter of taste, or is there a real (if a little academical) problem to solve.
It's a bit like pricing the credit default swap of, say, Germany. Germany will never default, and if it does, the party issuing the CDS is unlikely to be solvent and pay, so the price is random noise. Similarly, secondary exceptions overwriting the first one (the horror) are so rare that it's not possible to "price" the alternatives in an accurate manner (that is, to test them in practice.) I'd say that the only situation in which something like that can occur is with (an equivalent of) bad_alloc "overwriting" another (equivalent of) bad_alloc. In this case it is not clear to me why would one insist of knowing the precise bad_alloc that was thrown since an out of memory condition is an out of memory condition, no matter where it occurs. You may well want to know that a certain memory pool has been exhausted, but if you do, simply do not allocate in the error handling code from that same pool. Either way, given throw foo() << expr1 << expr2; if you really want to reliably throw foo() and consider expr1 and expr2 optional, the way to do it is: foo x; try { x << expr1 << expr2; } catch( ... ) {} throw x;