Somewhat OT, but hopefully informative in the context of this thread.

> On 26 Mar 2018, at 18:24, Jonathon Jongsma <jjong...@redhat.com> wrote:
> 
> As teuf mentioned in a different email, std::runtime_error in C++11 has a 
> const char* constructor:

Since the presence of this constructor was used repeatedly as an argument, I’ve 
asked a few times if someone could tell me why this constructor was added in 
C++ 11. So far, nobody answered. I did not think it was so hard to google it. 
Oh well, since nobody else took up the challenge, time for me to answer the 
question…

Here is one source giving a relatively short explanation: 
https://stackoverflow.com/questions/29052647/c11-introduced-exception-constructors-taking-const-char-but-why.
 I quote: "This allows (or at least is apparently intended to facilitate--see 
more below) the implementation to eliminate copies in cases where it can detect 
(by means that are not themselves standardized) that what's being passed is a 
string literal or something else with static storage duration.” See also the 
note at the end of that answer: "[ Oxford: The proposed resolution simply 
addresses the issue of constructing the exception objects with const char* and 
string literals without the need to explicit include or construct a 
std::string. ]”

So what happened is that the committee knew that having an std::string 
constructed for all runtime errors was problematic, as far back as 2000. This 
is defect 254, see http://std.dkuug.dk/jtc1/sc22/wg21/docs/lwg-closed.html. It 
was a bit annoying if implementors took a great deal of care and effort to 
ensure that you could throw an exception reliably in low-memory situations (see 
section 4.2.2 of 
https://github.com/itanium-cxx-abi/cxx-abi/blob/master/HP-exception-990818.pdf 
if you are curious about the kind of shenanigans I’m talking about) only to see 
all these effort thwarted by the (legacy) interface of std::runtime_error.

However, you can imagine that back in 2000, deciding to remove the std::string 
constructor was difficult. So the problem was not easy to fix, and it shouldn’t 
be too hard to believe that there was a lot of discussion (254 is listed as one 
of the hot topics for the Redmond meeting). Before the Oxford meeting, the 
decision was to accept throwing bad_alloc as a fact of life. But as you can see 
at the bottom of bug 254, the consensus on a better longer-term resolution for 
C++0x, which became C++11, was to add a const char * that would allow the 
implementation to special-case std::runtime_error and avoid the copy. In the 
Oxford meeting, that resolution was confirmed, and the change made it to C++11.

Out of curiosity, I checked both clang and g++, and they don’t actually store a 
string in std::runtime_error, I suspect in large part because of another 
related issue, namely the risk of throwing from string copy constructors. 
though they don’t seem to be doing the optimization either, because it’s quite 
hard relative to the benefits :-( So no worries, on clang, if you are really 
out of memory, you will not throw bad_allloc or end up in terminate(). No sir, 
the standard forbids it. No, instead, you will segfault writing into a null 
pointer (line 74 of 
https://llvm.org/viewvc/llvm-project/libcxx/trunk/src/include/refstring.h?view=markup
 if you are curious). So much better.

Bottom line: the very reason there is a const char * constructor in 
std::runtime_error is to provide a workaround for a known design bug. There is 
no value in blindly repeating that design bug.


Cheers,
Christophe

_______________________________________________
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Reply via email to