How to properly overload global new function to create objects - c++

I've seen a few places that show how to overload the global new function for allocations. What I would like to do is to have any call to 'new' call my function, which simply wraps the C++ standard 'operator new' and tracks memory usage. But I have a problem of not knowing how to construct the object because the type of the object is not available in the function:
void* operator new (std::size_t size)
{
// I don't know what to construct
}
struct MyClass{ int members[8];}
new MyClass; // I'd basically like to wrap the standard 'new' function allocator.

You are not supposed to construct an object inside of an overloaded operator new, only allocate raw memory of the requested size and return a pointer to it. The object’s constructor will be called on the returned memory after the operator new exits.
A new expression calls operator new specifying the size of the type, then calls the type’s constructor on that memory, and then returns a pointer to the object that was created.
Thus, an expression like new MyClass in your example is roughly equivalent (not exactly) to this:
//MyClass *cls = new MyClass;
void *mem = :: operator new (sizeof(MyClass));
MyClass *cls = static_cast<MyClass*>(mem);
cls->MyClass();
And the converse is true for the delete expression, which calls the type’s destructor, and then calls operator delete to deallocate the raw memory, eg:
//delete cls;
cls->~MyClass();
:: operator delete (cls);

It seems you're looking for a Factory function. A factory is a dedicated function (or even a class) that produced instances of a class.
E.g.
#include <memory>
struct MyClass { int members[8]; };
std::unique_ptr<MyClass> MyClassFactory() {
auto inst = std::make_unique<MyClass>();
// assign some stuff to members
return inst;
}

Related

Extra construction when using placement new with a storage class

In a situation where I want to avoid dynamic memory allocations, I'm replacing the new operator with a process that essentially uses the memory of some statically allocated object (the Storage class below). You can see a minimum working example below:
#include <cassert>
#include <iostream>
struct Object {
Object() { std::cout << "Creating a new object\n"; }
static void *operator new(size_t);
static void operator delete(void *p);
};
static struct {
Object where;
bool allocated = false;
} Storage; // 1
void *Object::operator new(size_t) {
assert(!Storage.allocated);
auto p = ::new (&Storage.where) Object; // 2
Storage.allocated = true;
return p;
}
void Object::operator delete(void *p) {
assert(Storage.allocated);
static_cast<Object *>(p)->~Object();
Storage.allocated = false;
}
int main() { Object *obj = new Object; } // 3
My question has to do with the number of calls to the constructor. When I run the above program, I expect to call the constructor twice (marked as 1 and 2 in the comments above) but the output I get is:
Creating a new object
Creating a new object
Creating a new object
Why is the constructor called thrice? I'd only expect constructor calls, by the static object and the call to placement new. I tried tracing the code with gdb, but it makes no sense to me, since position //3 is where the third call to the constructor originates.
The reason I want to know is because a case has emerged, where this extra constructor call causes unwanted side-effects; up until now, this extra call was unnoticed.
For some odd reason, your operator new calls the constructor when it should just allocate memory. This means that the call to new winds up calling the constructor of Object twice. There is one call in operator new and another call in main.
You probably want this:
void *Object::operator new(size_t) {
assert(!Storage.allocated);
Storage.allocated = true;
return reinterpret_cast<void *> (&Storage.where);
}
Imagine if the constructor took an integer parameter and the line in main looked like this:
Object *obj = new Object(7);
How would operator new know how to properly construct the object? That's not where you're supposed to do that!
Object *obj = new Object; does two things:
Allocates memory by calling operator new
Calls the constructor.
Your operator new calls the constructor as well, so the constructor is called twice by this statement (and once for the global variable initialization).
Note that delete is the same. delete obj; does two things:
Calls the destructor.
Deallocates memory by calling operator delete
Your operator delete shouldn't call the destructor either, because then the destructor is called twice.

Not able to create the object by new if new operator is overloaded and constructor is private

Can any body explain why i am not able to create the object using new if it is overloaded and constructor is private.
class A
{
A();
A(A const &obj);
A& operator =(A const &obj);
public:
void * operator new(Size_t size)
{
void * p = malloc (size);
return p ;
}
};
int main ()
{
A * p = new A() /*gives compile time error, saying constructor
is private.But cant we access private function from class
public function . as operator new is public function of class.*/
return 0;
}
Possibly you are conflating a new-expression with operator new.
An operator new is an allocation function, with a confusing name. It should better have been called _alloc or some such.
A new-expression
calls the allocation function, passing any specified arguments.
if that succeeds, calls the class constuctor with specified arguments.
Here the relevant constructor must be accessible.
if that fails, cleans up by deallocating memory (in the case where the allocation function has user defined arguments, a corresponding user defined deallocation function is called with the originally specified custom allocation function arguments).
In short, a new-expression guarantees that if you have fulfilled your obligations, then you will either have an initialized object at hand, or an exception with no memory leak.
One way to not fulfill your obligations is to defined a custom allocation function with no custom deallocation function. Then in the last bullet point above you get no cleanup, and hence a memory leak. But other than that, a new-expression is almost like a database transaction, it guarantees all-or-nothing.
Constructor is called after operator new. As you can see, in operator new you are only using malloc to allocate raw memory. Afterwards, default constructor is called to initialize class members. So new A() calls both, operator new and constructor, constructor is private, so you cannot access it, and thus compiler won't allow it.

Global new operator call syntax

Why the function with this signature
void* operator new (std::size_t size);
Cant be called in code like this
void* mem = new(100);
But rather it must be called like this
void mem = ::operator new(100);
Keyword new and operator new are different things.
Keyword new does:
Call operator new to allocate the memory. It can be overloaded for the type being allocated. Keyword new accepts optional arguments that get passed to operator new, this allows for placement new and non-throwing new syntax, see #include <new>.
Invoke the constructor of the object.
If the constructor throws, invoke the corresponding operator delete to free the memory. Note that if that operator delete is not accessible (not public), then new fails at compile time because operator delete cannot be called if the constructor throws and memory would be lost.
Keyword new cannot be overloaded, it always does these steps. This is operator new from step 1 what can be overloaded, normally along with operator delete from step 3.
In other words, X* p = new X(a, b, c); under the hood does something like (pseudo code):
X* p = static_cast<X*>(X::operator new(sizeof(X))); // 1. allocate memory
try {
p->X(a, b, c); // 2. invoke the constructor
}
catch(...) {
X::operator delete(p); // 3. free the memory if the constructor throw
throw;
}
In the above, if X does not overload its operator new, it is the global ::operator new that gets called. Note that X::operator new is implicitly static if overloaded.
There is a profound syntactical reason for this: placement new. With placement new, you can call a constructor without allocating memory for it. It's syntax is this:
#include <new>
Foo* foo = new(bufferPointer) Foo();
Obviously, part of this is the precise syntax you tried to call ::operator new()...

placement new signature

void someCode()
{
char memory[sizeof(Foo)];
void* place = memory;
Foo* f = new(place) Foo();
}
and the signature of new placement operator
void * operator new(size_t, void *p)
{
return p;
}
I don't get how a constructor could be bind to void *p since a constructor doesn't return any values ?
EDIT:
the following code for instance doesn't compile :
struct A{};
void f(void * p)
{
}
int main()
{
f(A());
std::cin.ignore();
}
The problem here is that C++ new is confusing:
there is the operator new, which you can overload and is in charge of allocating raw memory
there is the new expression (such as new A(5)) which under the covers first call the corresponding operator new overload and then performs the construction
Note that you have no say as to how the construction is performed: you supplied the type and the constructor parameters, the language does the rest, and there is no way to change this behavior.
Therefore, when you overload/override operator new, you are only affecting the raw memory allocation. The full syntax of the new expression can clear things up:
new (somepointer) A(5)
^~~~~~~~~~~~~ ^~~~
The first part is the list of arguments passed to operator new, on top of the size of the object (always passed). The second part corresponds to the constructor call. If there is no parameter to be passed to new (apart from the size which you don't control) then the first part may be omitted yielding the typical form new A(5).
You are free to overload new as much as you want, for example:
new (alignof(A)) A(5);
will call an operator new overload accepting a size_t as supplementary argument (representing the necessary alignment for the type):
void* operator new(size_t size, size_t alignment);
note: the first argument (size) is always there.
So, placement new is just a fancy overload in its own right:
void* operator new(size_t, void* p) { return p; }
There is not much interest in such an operator (it does nothing), however it helps maintaining a consistent syntax and allows you a way to specify where to build an object via using the new expression so that it is not necessary to create another syntax to allow such operation.
Constructor called after operator new executed. You posted not equivalent code. Equvalent would be
struct A
{
constructor (void* this);
}
int main ()
{
A a = A::constructor(operator new ());
}
It is not c++, just pceudocode
I think that the source of your confusion is an assumption that new(place) Foo(); is a single operation; it is not. Here is what's going on:
A placement new operator is called to allocate memory
A constructor is called to initialize the allocated memory
The first call needs to return the value (a void*). It is a block of memory suitable to store your object. The second call is a constructor. It gets the value from the placement new operator as its hidden this parameter, and performs its regular initialization tasks on it.

Do I need to overload delete if I have operator T *()?

If I have a template class A which holds a pointer, and A has an implicit conversion operator which will return that pointer, do I need to, or should I, define a delete operator for A, if I intent to apply delete to objects of this class?
You only need to define operator delete if you define operator new -- in which case you pretty much must do so.
That doesn't mean that something won't need to delete your A*s -- but you don't need to define any operators for that, it will work by default.
I believe that you've got something like the following:
template <typename T>
struct A {
T * t;
operator T* () { return t; }
};
An you intend to "apply delete to objects of this class", so by that I'm assuming you mean:
void foo ()
{
A<int> * p = new A<int>;
delete p; // Applying 'delete'
}
If this is the case, then the call to delete correctly destroys the object and frees the the memory allocated by the use of 'new' on the previous line and the answer to your question is 'no'.
Because you have declared a conversion operator to a pointer, it is possible to use delete on an object of type A<int> (a opposed to A<int>*). The use of delete will be applied to the result of calling the conversion operator:
void foo ()
{
A<int> a;
a.t = new int;
delete a; // Same as: delete a.operator T*()
}
Basics of how delete works:
The expression delete p, does two different things. Firstly, it calls the destructor for the object pointed to by p and then it frees the memory. If you define an operator delete member for your class then it will be that function which will be used by delete p to free the memory.
In general, you only define those operators when you want to control how the memory for dynamic objects of that class should be allocated or freed.
If your class owns this pointer, it should delete it in its destructor. Be aware that overloading this operator may be confusing, because the usual approach to obtain a pointer to an object is by taking its address.
Does you class A really need to define an implicit conversion operator? Maybe have a simple T* get() const method that returns the pointer, like the boost and std smart pointer do. Implicit conversion can cause all kinds of trouble.