8

Can a caught std::exception ever have what() being NULL?

Is the checking for e.what() below overhead?

//...
}
catch (const std::exception& e)
{
  std::string error;
  if(e.what())
    error = e.what();
}
Net Citizen
  • 5,174
  • 8
  • 38
  • 50

4 Answers4

13

The contents of the string is implementation defined, so I guess the answer is yes.

Edit: Belay that. The standard says:

virtual const char* what() const throw();
5 Returns: An implementation-defined NTBS.

So it must return a string, not just a pointer. And a string cannot be NULL. As others have pointed out it is easy to derive exceptions whose what() does return NULL, but I'm not sure how such things fit into standards conformance. Certainly, if you are implementing what() in your own exception class, I would consider it very bad practice to allow it to return NULL.

More:

For a further question addressing whether what() can return NULL, and similar exciting issues, please see Extending the C++ Standard Library by inheritance?

Community
  • 1
  • 1
  • But if you overwridde what and it is caught by just const std::exception& then it can be NULL, so probably best to check right? – Net Citizen Jun 24 '09 at 13:52
  • It's virtual though so it's possible for bad programmers to make it NULL – JaredPar Jun 24 '09 at 13:53
  • Interesting. Now, since I know that some folk like to implement what via an std::string and the c_str() method therein, I have to ask - can c_str() of a properly constructed std::string ever return NULL? (I'm asking because I've got this situation in the codebase I work with and I want to know if I need to go add some TODOs or not). – Michael Kohne Jun 24 '09 at 13:56
  • c_str() for std:;string can never return NULL. –  Jun 24 '09 at 13:58
  • @Net Citizen: The standard saying that it must not be NULL is a law as in "court", not a "physical law" -- it only says something should not be done, it can't prevent someone from breaking the law. (There's no reasonable way that C++ compiler/library implementors could actually provide a "physical law" that would prevent such code from compiling in C++.) – j_random_hacker Jun 24 '09 at 13:59
  • 1
    @j_random_hacker, they could in this case if the chose the return to be std::string vs. const char*. This would enforce at strong level at least a valid empty string. But much too late for that :(. – JaredPar Jun 24 '09 at 14:03
  • 2
    @JaredPar Returning a string involves memory allocation, which might be undesirable if you were trying to report a memory allocation failure. –  Jun 24 '09 at 14:08
  • Intentionally not a std::string - it has to work for std::bad_alloc::what() – MSalters Jun 24 '09 at 14:08
  • 4
    @Net Citizen - I'd actually go with a code review of all exception classes in the system and make sure they don't return NULL. There probably aren't that many in a given system, and you can save a lot of excess code by doing a little work up front. – Michael Kohne Jun 24 '09 at 14:17
  • 2
    The key point is that to have proper inheritance, base class promises must be preserved. Therefore if the base class function promises never to return NULL (which appears to be the case here), any derived classes must promise the same, otherwise the inheritance is improper (broken). – markh44 Jul 02 '09 at 12:23
5

If someone has inherited from std::exception and overridden what to return NULL, then this is possible.

   class CMyException : public std::exception
   {
   ...
       virtual const char * what () const {return NULL;}
   };

Despite Neil's excellent find in the standard, It might still be good to check for NULL. Although the specifications of what child classes of std::exception state they should not return a NULL, nothing in your compiler is going to enforce this and the above code will still be legal according to the language.

This may be an ideal situation to use an assert...

 assert(except.what() != NULL);

or

 if (except.what() != NULL)
 {
      ... normal processing ...
 }
 else
 {
      assert(false);
 }

because this is a case where something probably should never ever happen, and you are assuming it shouldn't happen, but would still like to know (in debug mode) when your assumptions are shown to be wrong. Then you can either address your incorrect assumption or address the incorrect code which may be going against your assumption (make sure what() doesn't return NULL).

Doug T.
  • 64,223
  • 27
  • 138
  • 202
2

Of course it can be NULL:

class myexception: public exception
{
  virtual const char* what() const throw()
  {
    return NULL;
  }
} myex;
schnaader
  • 49,103
  • 10
  • 104
  • 136
  • 1
    It is possible to do this **in the language** (i.e. your code will compile), but this is outlawed by the C++ standard -- see Neil's answer. IOW, don't do this, since other people's code might rely on you not doing this. – j_random_hacker Jun 24 '09 at 13:55
  • I don't think it is "outlawed" - the standard specifies the behaviour of std::exception::what - it doesn't seem to make any requirements of user classed deriving from std::exception. – JoeG Jan 19 '10 at 23:04
0

As many others have pointed out, what() shouldn't return a null pointer but it might. The runtime overhead of a null test is only incurred in the exceptional case where, presumably, it is less important.

In any case, I'd recommend at least using an assert.

If code space is also a concern, hopefully the assert, your testing, code reviews and other QA will be complete enough to track down any offending, non-compliant exceptions before you ship.

Also, be careful with exception handling code that can itself throw (for example, as others have noted, allocating memory with std::string while processing a std::bad_alloc exception.)

jwfearn
  • 28,781
  • 28
  • 95
  • 122