std::exception Why what() is returning a const char* and not a string?

428 views
Skip to first unread message

Francis Andre

unread,
Jun 28, 2015, 4:20:29 AM6/28/15
to std-dis...@isocpp.org
Hi

The std::exception::what() method is defined as

virtual const char * what() const;

Why this method is returning a const char* and not a string?

(One cannot easily override this method in a derivative class because of its return signature)

FA

Ville Voutilainen

unread,
Jun 28, 2015, 4:37:27 AM6/28/15
to std-dis...@isocpp.org
On 28 June 2015 at 11:20, Francis Andre
<francis.and...@orange.fr> wrote:
> Hi
>
> The std::exception::what() method is defined as
>
> virtual const char * what() const;
>
> Why this method is returning a const char* and not a string?

The expectation is that the exception type holds the data, so it can
return a pointer to it,
no need to construct a separate string.
Furthermore, it's trying to avoid the user having to #include <string>
when using
exceptions like bad_cast.

> (One cannot easily override this method in a derivative class because of its
> return signature)

How so?

Francis ANDRE

unread,
Jun 28, 2015, 5:26:23 AM6/28/15
to std-dis...@isocpp.org
How could a derivative class what() method return easily the base class
what() message with a specific prefix for example?
>

Thiago Macieira

unread,
Jun 28, 2015, 12:31:53 PM6/28/15
to std-dis...@isocpp.org
On Sunday 28 June 2015 11:37:26 Ville Voutilainen wrote:
> On 28 June 2015 at 11:20, Francis Andre
>
> <francis.and...@orange.fr> wrote:
> > Hi
> >
> > The std::exception::what() method is defined as
> >
> > virtual const char * what() const;
> >
> > Why this method is returning a const char* and not a string?
>
> The expectation is that the exception type holds the data, so it can
> return a pointer to it,
> no need to construct a separate string.
> Furthermore, it's trying to avoid the user having to #include <string>
> when using
> exceptions like bad_cast.

Most importantly: it's to support returning a suitable error string without
allocating memory. Have you ever tried to allocate memory in response to an
OOM condition?

> > (One cannot easily override this method in a derivative class because of
> > its
> > return signature)
>
> How so?

I think he wants to change the return type. The answer is: don't change the
return type.

If your exception could allocate memory at the throw point, simply store the
prepared what() message in its body and free it on the destructor. There's a
widely used class that manages a const char* memory block for you, it's called
std::string.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358

Howard Hinnant

unread,
Jun 28, 2015, 12:45:20 PM6/28/15
to std-dis...@isocpp.org
On Jun 28, 2015, at 12:31 PM, Thiago Macieira <thi...@macieira.org> wrote:
>
> If your exception could allocate memory at the throw point, simply store the
> prepared what() message in its body and free it on the destructor. There's a
> widely used class that manages a const char* memory block for you, it's called
> std::string.

Your advice is good except for one detail: Don’t use std::string to manage the memory for the message. Exceptions should have noexcept copy constructor and copy assignment. std::string can’t supply these (it is no longer COW). To manage this memory when it is allocated at construction time you need an immutable reference counted string. Fortunately the standard has one of those too. It doesn’t have a name, but it is under every exception class in chapter 19.

Use (for example) std::runtime_error to manage the message you allocate on construction. You can derive from it or embed it. You can treat std::runtime_error as an immutable reference counted string class. If the code looks just too weird to pass code review, you can do this:

using immutable_string = std::runtime_error;

Howard

Francis ANDRE

unread,
Jun 28, 2015, 4:18:26 PM6/28/15
to std-dis...@isocpp.org
Thanks for your ironical answer.. but I remind you the initial question:

"Why this method is returning a const char* and not a string?"

(From my point of view, a virtual function that returns a const char* is a non sense, and yes, I would like the next C++ standard changes the returned type of the what() method to std::string)



Patrice Roy

unread,
Jun 28, 2015, 5:01:52 PM6/28/15
to std-dis...@isocpp.org
As Ville mentioned, there's a problem with constructing and returning something that cause raise an exception in a class used to raise an exception. As far as I know, that's one of the key reasons why const char* is used there.

If you think that out-of-memory is so bad that programs should just crash whem that happens, and thus that a bad_alloc or such is acceptable when executing throw something_or_other(some_message); with some_message of type std::string andf sufficiently long to require dynamic memory allocation, then maybe you should express this position formally in a paper in order to clarify your argument and make the discussion easier. There will probably be opposition from people who write critical systems, but it might be interesting to hear both sides.





--

--- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.

Thiago Macieira

unread,
Jun 28, 2015, 8:22:46 PM6/28/15
to std-dis...@isocpp.org
On Sunday 28 June 2015 22:18:17 Francis ANDRE wrote:
> Thanks for your ironical answer.. but I remind you the initial question:
>
> "Why this method is returning a const char* and not a string?"

I thought that was answered: because you cannot construct a std::string
without allocating memory. See also Howard's answer for stricter requirements
than I had realised.

> (From my point of view, a virtual function that returns a const char* is a
> non sense, and yes, I would like the next C++ standard changes the returned
> type of the what() method to std::string)

Not going to happen.

Nathan Ernst

unread,
Jun 29, 2015, 2:05:26 AM6/29/15
to std-dis...@isocpp.org
Is there perhaps a middle ground, here, where the base standard exception types accepts a const-reference to an immutable-reference-counted string in their constructor (where the const-ref is a bit of a joke and it copies the goods and increments the reference count -- probably a better way of implementing this)? Said ref-counted internally held should behave as Howard has already indicated, but would allow for dynamically created error messages as requested earlier in the thread (and if said error message could not be created due to allocation errors, fail with a bad_alloc, or something more fitting).

Regards,
Nate

Francis ANDRE

unread,
Jun 29, 2015, 6:00:07 AM6/29/15
to std-dis...@isocpp.org
Ok my tired brain  missed this important use case: the bad_alloc exception...
Sorry for the noise of this topic

FA

Thiago Macieira

unread,
Jun 29, 2015, 11:44:07 AM6/29/15
to std-dis...@isocpp.org
On Monday 29 June 2015 01:05:25 Nathan Ernst wrote:
> Is there perhaps a middle ground, here, where the base standard exception
> types accepts a const-reference to an immutable-reference-counted string in
> their constructor (where the const-ref is a bit of a joke and it copies the
> goods and increments the reference count -- probably a better way of
> implementing this)? Said ref-counted internally held should behave as
> Howard has already indicated, but would allow for dynamically created error
> messages as requested earlier in the thread (and if said error message
> could not be created due to allocation errors, fail with a bad_alloc, or
> something more fitting).

I don't understand why that can't be achieve with the current infrastructure.

Tony V E

unread,
Jun 30, 2015, 1:19:33 AM6/30/15
to std-dis...@isocpp.org
If we could change it, I suspect string_view might work.  But changing it would break way too much code.
We could add a new function (called wtf() ?) that returned a string_view, while maintaining/deprecating the old what() function, but is it worth it?

Reply all
Reply to author
Forward
0 new messages