Segmentation error instead of calling constructor

I am trying to slightly modify the built-in distribution function:

#include <iostream> #include <cstdlib> #include <new> struct A { int a; A(){ std::cout << "Constructor\n"; a = 3; } void* operator new(std::size_t t) noexcept { ::operator new(t); return NULL; } }; int main() { new A(); } 

demo

Instead of calling the constructor, I have a segmentation fault . Could you explain this behavior?

+8
c ++ constructor
source share
3 answers

You have an error because calling ::operator new() can call std::bad_alloc , violating the exception specification of your class allocator (zybox answer shows how to fix this). However, this is very unlikely in such a small program. It is also nice to override operator new() without providing operator delete() , although I cannot find an explicit requirement for both to be found in the same scope.

Returning a null pointer from your allocator is both a legal and a correct way to indicate a denial of allocation. 3.7.4.1 in the Standard states that:

A distribution function that cannot allocate storage can call the currently installed function of the new handler (18.6.2.3), if any. [Note. The distribution function provided by the program can get the address of the currently installed new_handler using the std::get_new_handler (18.6.2.4). - end note] If a distribution function declared with an exception-spec specification (15.4) cannot allocate storage, it should return a null pointer. Any other distribution function that cannot allocate storage should indicate failure only by throwing an exception (15.1) of the type that will correspond to a handler (15.3) of the type std :: bad_alloc (18.6.2.1).

Then in 5.3.4:

If the distribution function returns null, initialization is not performed, the release function must not be called, and the value of the new expression must be zero.

The code is legal in a way that ::operator new() does not throw out - the expression new A() in main() evaluates to a null pointer, which is normal because it never gets dereferenced.

You should also not receive a constructor call. What you should get is a memory leak, since in your allocator there is no ::operator delete() call corresponding to ::operator new(t) .

+5
source share

Your new operator statement contains a null pointer, and as such actually returns nothing.

The null function return false; is return false; or just return; , but it should be warned: duplicating a pointer using the new operator causes a memory leak if you are not careful. To get around this, simply delete(t) when you are done.

The following code will fix your problem:

 #include <iostream> #include <cstdlib> #include <new> struct A { int a; A(){ std::cout << "Constructor\n"; a = 3; } void* operator new(std::size_t t) noexcept { return ::operator new(t, std::nothrow); } }; int main() { new A(); } 
+1
source share

The source code simply returns NULL from A::operator new , quietly forgetting the result of returning ::operator new (memory leak). The reason for the failure is that the returned pointer is then used as the this pointer for the new A object. Since this pointer is NULL , all that the constructor does with the object (by assigning a = 3 ) is the dereference of NULL . This leads to disruption of segmentation. The answer to zyboxinternational above gives a good solution, and the comments of both previous posters are very relevant.

0
source share

All Articles