Why was bad_alloc (const char *) closed in Visual C ++ 2012?

I'm just trying to compile a slightly larger project using Visual Studio 2012 Release Candidate, C ++. The project was / compiled using VS2010. (I'm just greedy to get C ++ 11 things, so I tried. :)

Besides the things that I can explain myself, the project uses the following code:

ostringstream ostr; ostr << "The " __FUNCTION__ "() failed to malloc(" << i << ")."; throw bad_alloc(ostr.str().c_str()); 

Now the compiler complains

 error C2248: 'std::bad_alloc::bad_alloc' : cannot access private member declared in class 'std::bad_alloc' 

... which is true. This constructor version is now closed.

What was the reason to make this design private? Is the C ++ 11 standard recommended not to use this constructor with an argument?

(I can imagine that if the distribution is not successful, it can cause more problems to try to build something new. However, this is only my guess.)

Thanks Petr

+6
source share
2 answers

The C ++ 11 standard defines bad_alloc as such (18.6.2.1):

 class bad_alloc : public exception { public: bad_alloc() noexcept; bad_alloc(const bad_alloc&) noexcept; bad_alloc& operator=(const bad_alloc&) noexcept; virtual const char* what() const noexcept; }; 

Without a constructor that takes a string. The vendor providing such a constructor will make the code using it not portable, as other vendors are not required to provide it.

The C ++ 03 standard defines a similar set of constructors, therefore VS did not correspond to this part of the standard even before C ++ 11. MS is trying to make VS standard as much as possible, so they probably just used the case (new VS, new standard), to fix incompatibility.

Edit: Now that I saw the VS2012 code, it’s also clear why the mentioned constructor has remained closed and not completely removed: it seems that this is only one use case for this constructor, in the bad_array_new_length class. Therefore bad_array_new_length declared friend in bad_alloc and therefore can use this private constructor. This dependency could be avoided if bad_array_new_length just saved the message in the pointer used by what() , but that is not much code.

+14
source

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...); } 
+1
source

Source: https://habr.com/ru/post/918635/


All Articles