If you are used to sending a message when you throw std :: bad_alloc, a suitable method is to define an inner class that comes from std :: bad_alloc and override 'what needs to be provided to the corresponding message.
You can make the class public and call the assignment constructor directly, or create a helper function, such as throw_bad_alloc, that takes parameters (and additional scalar information) and stores them in the inner class.
The message is not formatted before what is called. Thus, unwinding the stack can free some memory so that the message can be formatted for the actual reason (memory exhaustion, size of the wrong request, heap corruption, etc.) on the catch site. If formatting fails, simply assign and return a static message.
Cropped example:
(Tip. The copy constructor can simply assign _Message nullptr, rather than copy the message, because the message is formatted on demand. The move constructor, of course, can just confiscate it :-).
class internal_bad_alloc: public std::bad_alloc { public: // Default, copy and move constructors.... // Assignment constructor... explicit internal_bad_alloc(int errno, size_t size, etc...) noexcept: std::bad_alloc() { // Assign data members... } virtual ~internal_bad_alloc(void) noexcept { // Free _Message data member (if allocated). } // Override to format and return the reason: virtual const char* what(void) const noexcept { if (_Message == nullptr) { // Format and assign _Message. Assign the default if the // format fails... } return _Message; } private: // Additional scalar data (error code, size, etc.) pass into the // constructor and used when the message is formatted by 'what'... mutable char* _Message; static char _Default[]; } }; // // Throw helper(s)... // extern void throw_bad_alloc(int errno, size_t size, etc...) { throw internal_bad_alloc(errno, size, etc...); }
Merkx source share