overloading new and delete operator with optional arguments - c++

#include <new>
#include <cstdlib>
#include <iostream>
#include <stdexcept>
struct foo {};
inline void* operator new(size_t size, foo*) throw (std::bad_alloc)
{
std::cout << "my new " << size << std::endl;
return malloc(size);
}
inline void operator delete(void* p, foo*) throw()
{
std::cout << "my delete" << std::endl;
free(p);
}
int main()
{
delete new((foo*)NULL) foo;
}
Output (via ideone):
my new 1
My thinking was that C++ would free an object new'd with additional arguments with its matching delete of the same arguments, but I was obviously incorrect.
What is the correct way to get the code above to call my overloaded delete?

When you use any form of placement new, except for the std::nothrow_t versions, you need to explicitly destroy the object and release its memory with whatever means you see fit. The overloaded version of operator delete() is still required to exist, however, because it is used if construction of the object throws an exception! In this case, no pointer is returned because an exception is thrown. Getting rid of the memory has, thus, to be done in this process of allocation.
That is, you main() should look something like this:
int main()
{
foo* p = new (static_cast<foo*>(0)) foo;
p->~foo();
operator delete(p, static_cast<foo*>(0));
}

Related

C++: Overloaded New call constructs object automatically

I'm trying to overload the new operator in order to allocate my own memory, but I still need to construct the object.
That's why I decided to pass the parameters through a variadic template in order to feed the object's constructor properly.
The constructor is called twice in this example, I can't explain why.
It seems that the overloaded new calls automatically the constructor.
#include <stdlib.h>
#include <iostream>
#include <new>
class A
{
public:
template<typename... Args>
void *operator new(size_t sz, Args ...parameters)
{
void *mem = ::operator new(sizeof(A));
A *var = ::new (mem) A(parameters...);
return var;
}
A() : num(0) { std::cout << "Default" << std::endl; }
A(int nb) : num(nb) { std::cout << "Integer = " << num << std::endl; }
const int num;
};
int main()
{
A *obj = new A(3);
std::cout << "Obj result = " << obj->num << std::endl;
}
Fixed, there is not reason to try to call the constructor within the overload, the object will be constructed at returned void*'s pointed allocated memory.
I'm trying to overload the new operator in order to allocate my own memory, but I still need to construct the object.
No you don't. operator new by definition initializes the object. See [expr.new]/15:
A new-expression that creates an object of type T initializes
that object as follows:
— If the new-initializer is omitted, the object is
default-initialized (8.5); if no initialization is performed, the
object has indeterminate value.
— Otherwise, the new-initializer is interpreted according to the
initialization rules of 8.5 for direct-initialization.
At a minimum, your overload can look like this:
void *operator new(size_t sz)
{
return ::operator new(sizeof(A));
}
The static keyword is optional.

why overloaded new operator is calling constructor even I am using malloc inside overloading function?

I am trying to understand overloading new operator. I wrote the code as below.
#include <iostream>
#include <cstdlib>
#include <new>
using namespace std;
class loc
{
int lo, la;
public:
loc()
{
}
loc(int x, int y)
{
cout << "In constructor\n";
lo = x;
la = y;
}
void show()
{
cout << lo << " ";
cout << la << endl;
}
void *operator new(size_t sz);
void operator delete(void *p);
};
void *loc::operator new(size_t sz)
{
cout << "in Overloaded new\n";
void *p = malloc(sz);
return p;
}
void loc::operator delete(void *p)
{
cout << "in Overloaded delete\n";
free(p);
}
int main()
{
loc *p1 = new loc(10, 20);
p1->show();
delete p1;
return 0;
}
I thought it won't call the constructor because I overloaded the new operator with malloc function call inside overloading function. But the output is as below.
in Overloaded new
In constructor
10 20
in Overloaded delete
That means constructor is getting called. How this is possible? Does this mean will malloc() call constructor?
A new expression results in two separate things happening: allocation of the memory needed by the object begin created, and initialization of the object.
The new operator, on the other hand, just handles the allocation part. When you overload the new operator with respect to a specific class, you are replacing the allocation of memory to the object.
This division of functions makes sense when you realize that not all objects are allocated on the heap. Consider the following case:
int main() {
string someString;
..
}
The local variable is not dynamically allocated; new is not used; however the object still needs to be initialized so the constructor is still called. Note that you did not need to explicitly call the constructor - it is implicit in the language that an appropriate constructor will always be called to initialize an object when it is created.
When you write a 'new expression', the compiler knows to emit instructions to invoke the new operator (to allocate memory as needed) and then to call the constructor (to initialize the object). This happens whether or not you overload the new operator.

Why class constructor being called for overloaded operator new?

I am using c++11 (g++ v4.7.2)
I've overloaded operator new and operator delete for "Base" class. Apparently they should not call constructor/destructor upon call of new/delete because I've not implemented ctor/dtor call in overloaded new/delete. But the output is contrary to that
//Output of below program
Base new opnd.cpp 87
Base ctor
10
Base dtor
Base delete
Why ctor/dtor are being called for overloaded operator new/delete?
#include <iostream>
using namespace std;
#define NEW new(__FILE__, __LINE__)
#define DELETE delete
class Base
{
public:
Base():m_i(10){ cout << "Base ctor" << endl; }
virtual ~Base(){ cout << "Base dtor" << endl; }
void* operator new(size_t size, const char* file, int line) throw(std::bad_alloc);
void operator delete(void *rawMem, size_t size);
int geti(){ return m_i; }
private:
int m_i;
};
void* Base::operator new(size_t size, const char* file, int line) throw(std::bad_alloc)
{
void *p;
cout << "Base new " << file << " " << line << endl;
//Handle 0 byte requests
if(size == 0)
size = 1;
if(size != sizeof(Base))
{
return ::operator new(size); // To handle new requests for derived classes
}
while(true)
{
p = malloc(size);
if(p)
return p;
new_handler globalHandler = set_new_handler(0);
set_new_handler(globalHandler);
if(globalHandler) (*globalHandler)();
else throw std::bad_alloc();
}
}
void Base::operator delete(void *rawMem, size_t size)
{
cout << "Base delete" << endl;
if(rawMem == 0)
return;
if(size != sizeof(Base))
{
::operator delete(rawMem); //To handle delete requests for derived classes
return;
}
free(rawMem);
}
int main()
{
Base *b = NEW Base;
cout << b->geti() << endl;
DELETE b;
return 0;
}
An operator new function (be it the global one or a class-specific one) is not the entire implementation of a new expression. It's only the allocation function. When you write new T in your code, the following happens:
An appropriate allocation function named operator new is chosen and called to obtain space for the object.
T's constructor is called on the space obtained from point 1.
This means there is no way to bypass constructor invocation by writing your own operator new - invoking the constructor is done by the language, not by the allocation function.
'Operator new' and 'new Operator' are two distinct things. When we use new to create some object like
MyClass* ca= new MyClass();
we are using the 'new Operator'. It does two things:
Calls 'Operator new' to allocate enough memory. It can be overloaded as you did.
Calls the constructor of the object to set initialization data.
These 2 steps will be executed no matter how the space is allocated. Hence after allocating memory using your overloaded 'Operator new', the constructor is called.

why does sgi stl source code use the double-colon in front of the operator new function?

I am reading the source code of SGI standard template library. I find that the operator new function always has a double-colon in front of it. Like this:
T* tmp = (T*)(::operator new((size_t)(size * sizeof(T))));
operator new can be directly called without adding the :: field, then why do the stl coders write it in this way? What trap or situation may it come to if we don't use the :: in front of them.
You can overload operator new for a class and prefixing it with "::" will call the global "default" operator new instead of a possible overload. For example:
#include <iostream>
class Foo
{
public:
Foo() { std::cout << "Foo::Foo()" << std::endl; }
void * operator new(size_t )
{
std::cout << "Foo::operator new()" << std::endl;
return static_cast<Foo *>(malloc(sizeof(Foo)));
}
};
int main()
{
Foo foo;
std::cout << "----------------------" << std::endl;
Foo * p = new Foo;
std::cout << "----------------------" << std::endl;
Foo * q = ::new Foo;
}
will print
Foo::Foo()
----------------------
Foo::operator new()
Foo::Foo()
----------------------
Foo::Foo()
Edit: The code snipped is indeed not about operator new that is defined in a class scope. A better example would be this:
#include <iostream>
namespace quux {
void * operator new(size_t s)
{
std::cout << "quux::operator new" << std::endl;
return malloc(s);
}
void foo()
{
std::cout << "quux::foo()" << std::endl;
int * p = static_cast<int*>(operator new(sizeof(int)));
}
void bar()
{
std::cout << "quux::bar()" << std::endl;
int * p = static_cast<int*>(::operator new(sizeof(int)));
}
} // namespace quux
int main()
{
quux::foo();
quux::bar();
}
which prints
quux::foo()
quux::operator new
quux::bar()
::operator new in C++ is the global memory allocator that is called every time a certain amount of bytes is needed for a single object. Note that the return value is a void * and that ::operator new(size_t) deals with raw bytes, not objects.
It is basically the C++ counterpart of malloc with simply a funny name.
A separate global allocator ::operator new[](size_t sz) is instead used to allocate memory for arrays of objects.
These two operators, their counterparts ::operator delete and ::operator delete[] and also the nothrow version of the allocators are used for all memory needs of the C++ runtime.
They may be implemented in terms of calls to malloc/free or not. What is guaranteed is that malloc and free dont use them (thus you can call malloc and free if you want to reimplement these functions without the risk of infinite recursion).
To call the operator new from the global namespace, in case the user (or someone) else decided to have a new operator.
Double-colon is used to prevent T::operator new() to be called (if
defined).

how placement new works in c++? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++'s “placement new”
I just learned about the placement new operator and tried creating my own memory manager.
Here is the code of my template base class for Memory
#ifndef _MEMORY_BASE_H_
#define _MEMORY_BASE_H_
//=========================================!
#include <new>
#include <exception>
#include <iostream>
//=========================================!
using namespace std;
//=========================================!
template <typename T>
class Memory_Base
{
public :
//standard new
void* operator new(size_t T);
// placement new
void* operator new(size_t T,void* pAddress);
//standard delete
void operator delete(void* pAny);
};
//=========================================!
// Implementation
//=========================================!
template <typename T>
void* Memory_Base<T>::operator new(size_t T)
{
cout << "Memory_Base<T>:: new called" << endl;
void* pTemp = malloc(sizeof(T));
if(!pTemp)
throw bad_alloc();
else
return pTemp;
}
//=========================================!
template <typename T>
void* Memory_Base<T>::operator new(size_t T,void* pAddress)
{
cout << "Memory_Base<T>:: placement new called" << endl;
return pAddress;
}
//=========================================!
template <typename T>
void Memory_Base<T>::operator delete(void* pAny)
{
cout << "Memory_Base<T>:: delete called" << endl;
free(pAny);
}
//=========================================!
#endif
Now, i inherited myclass from above class,in another header file , something like as below
#ifndef _MY_CLASS_H_
#define _MY_CLASS_H_
//=========================!
#include "Memory_Base.h"
//=========================!
class MyClass :public Memory_Base<MyClass>
{
private :
int ma;
public :
MyClass():ma(-1){}
~MyClass(){}
};
//============================!
#endif
Now, in my main, i am trying to create objects of myclass in the following manner
//============================!
#include "MyClass.h"
//============================!
int main()
{
// This is how new for MyClass is called
MyClass* pMyClass = new MyClass();
// This is how placement new for MyClass is called
MyClass obj[10];
MyClass* pMyClass1 = new(&obj)MyClass();
return 0;
}
//============================!
Questions ::
1. When i run main, the base address of obj and pMyClass1 were the same, as expected. However, i am just returning the pointer pAddress, then how the placement new works ?
my obj[10], is in stack, but, the destructor is not getting called.
Any ideas ?
Atul
P.S :: I have to implement the new[] and delete[] in Memory_Base.
MyClass obj[10];
Allocates and creates 10 objects of the type MyClass on the local storage.
Further,
MyClass* pMyClass1 = new(&obj)MyClass();
Just calls the constructor MyClass::MyClass(). The this pointer in the MyClass constructor will be equal to &obj. The returned pointer pMyClass1 will therefore be equal to &obj.
Also, In case of placement new it is your responsibility to destroy the placed object by explicitly calling the destructor, the placed objects destructor wont be called implcitly.
Since, the array of objects since placed on stack will be deallocated once the program returns in your case.