memory management c++ (peeling operator new() and delete())
DESCRIPTION
This presentation will help reader in understanding some basic concept of dynamic memory management in C++.TRANSCRIPT
Memory Management in C++Peeling operator new() and delete()
Sameer Singh Rathoud
About presentation
This presentation will help reader in understanding some basic concept of dynamic
memory management in C++.
operator new() and delete()
operator “new()” and “delete()” are the built-in language support for
dynamically allocation and de-allocation of memory In C++.
About operator new()
• Operator “new()” can be user defined or built-in.
• If a programmer don’t specify operator “new()”, built-in operator
“new()” will be used by default.
• Operator “new()” can be defined globally or as a member of class.
• There should be only one global operator “new()” with particular types of
parameter in an executable.
• Operator “new()” global/local only allocates the memory from heap.
• Memory allocated on heap is having lifespan beyond its original scope.
So to prevent the memory from leaking, programmer explicitly need to
release the memory
Advantages of new()
Programmer don’t need to define the size of (“sizeof”) memory to allocate while
using operator “new()”.
Provide flexibility to the programmer to overload the operator “new()” as per
need.
• Improves code readability.
• No need of casting explicitly.
• Returns null pointer on failure and provide flexibility to the user to handle the
scenario.
Minimal definition of operator new()
This is the minimal definition of operator“new()” taking the argument as size of
memory to be allocated and returning thevoid* of the memory allocated by “malloc”.
extern "C" void *malloc (size_t);
void* operator new(size_t sz) {
return malloc (sz);
}
class A {
};
int main() {
A *a = new A();
return 0;
}
Handling new() failure
A Programmer can handle failure ofoperator “new()” in two ways:
• Programmer can use “nothrow”
option and check for the null
pointer.
• Programmer can use “try –
catch” block to catch
“std::bad_alloc exception”.
Method 1:
A *p_a = new(nothrow) A();
If(!p_a)
{
// new() failure handling
}
Method 2:
try {
A *p_a = new A();
}
catch(std::bad_alloc& ex) {
// new() failure handling
}
Handling new() failure - _new_handler and set_new_handler
• If operator “new()” fails to find memory it calls pointer to a function
“_new_handler()”.
• If “_new_handler()” again fails to find memory it throws “std::bad_alloc
exception”.
• A programmer can set his own “_new_handler” using function
“set_new_handler()”.
Handling new() failure - _new_handler
“_new_handler()” example
void _new_handler() {
cout << "Failed to allocate memory" << endl;
exit(1);
}
extern "C" void *malloc (size_t);
void *operator new (size_t size) {
void *p = NULL;
while ((p = malloc (size)) == 0)
if (_new_handler)
(*_new_handler)();
else
return 0;
return p;
}
Handling new() failure - set_new_handler
“set_new_handler()” example
void newFailed() {
cout << "Failed to allocate memory" << endl;
exit(1);
}
int main() {
set_new_handler(newFailed);
A *p_a = new A();
return 0;
}
malloc() and free() with C++
A programmer can use “malloc()” and “free()” routines with C++
Caution:
• Never mix “new()” with “free()” or “malloc()” with “delete()”.
• Always remember “malloc()” and “free()” do not call constructor and
destructor. So be careful to use these routines with class objects.
C++ doesn’t support “realloc()” like operator.
Allocation and de-allocation of array
• Operator “new()” and “delete()” can also be used for allocating and de-
allocating of memory for array of objects.
• When calling the operator “delete()” for the pointer to an array, a
programmer has to use [] with “delete()” to free entire array’s memory.
A *p_a1 = new A();
A *p_a2 = new A[10];
delete p_a1; // deleting object
delete[] p_a2; // deleting array of object
Construction and destruction
Construction of an object happens in 3 steps:
• Allocate the sufficient memory to hold the object.
• If allocation is successful call the constructor and create an object in that
memory.
• Store the address of the allocated memory in the specified pointer.
A *p_a = new A();
• Allocate the sufficient memory to hold the object of class A.
• If allocation is successful call A() and create an object of A in that memory.
• Store the address of the allocated memory in p_a.
Construction and destruction continue …
Destruction of an object happens in 2 steps:
• Call the destructor of A (~A())
• De-allocate the memory pointed by p_a;
delete p_a;
Construction and destruction continue …
• Allocation and de-allocation of memory is handled by operator “new()”
and “delete()”.
• Construction and destruction of an object is handled by constructor
and destructor.
• Before invocation of constructor memory has been already allocated
for the object, so that constructor can do its work.
• Destructor only destructs the object and not responsible for cleaning
up the memory and after destructor completes its job then only
memory will get cleaned up.
Object placement syntax
• As default operator “new()” allocates the memory from the pool of free
memory (heap).
Always this might not be the requirement. May be user wanted to create an object
at any specific location (e.g. in case of shared memory).
• As the solution of this C++ provides default placement version of operator
“new()”, to create an object at specified location.
void *operator new() (size_t, void *p) { return p; }
Object placement syntax continue …
Usage:
void* vp_a = shm_malloc (sizeof (A)); // allocate memory in shared memory
A* p_a = new() (vp_a) A; // construct a “A” object there.
As we have constructed an object in the memory already got allocated, we need a
way to destroy the object without releasing the memory.
p_a->(~A());
shm_free(p_a);
Object placement syntax continue …
Placement syntax can also be used to pass additional parameters.
Placement syntax can be used to resize the allocated memory, but can only be
used for built-in types, because of object construction and destruction issues
and highly not recommended.
Class specific operator new() and delete()
A programmer can specify a class specific operator “new()” and “delete()”.
class A {
public:
void* operator new(size_t);
void operator delete(void*);
};
Now “A::operator new()” will be used
instead of global operator “new()”. The
specified version of operator “new()” will only
be work for class A and classes derived from A.
It won’t be used for array of objects, as we
have not specified the array version of operator
“new()”.
void* operator new[](size_t);
Overloading operator new() and delete()• A programmer can specify any number of overloaded operator “new()” with
different signature.
• It is not possible to overload operator “delete()” with different signature.
• Class specific overloaded operator “new()” and “delete()” obeys the same
scope rule as other member functions of class.
• And class specific operator “new()” and “delete()” will hide the global
operator “new()” and “delete()”, which may give error in case of incorrect
usage (like no operator “new()” found for class with specified signature).
class A {
public:
void* operator new(size_t, int);
};
A* p_a = new() A; // will get error
Overloading operator new() and delete() continue …
A programmer can solve thus problem in few ways.
• Define a class specific default operator “new()”.
• Can explicitly give call to global operator
“new()”.
• Can give the default value to the argument.
Method 1:
class A {
public:
void* operator new(size_t,
int);
void* operator new(size_t);
};
A* p_a = new() A;
Method 2:
A* p_a = ::new() A;
Method 3:
class A {
public:
void* operator new(size_t,
int i = 0);
};
A* p_a = new() A;
Variants of built-in operator new() and delete()
• void* operator new(std::size_t) throw (std::bad_alloc);
• void* operator new[](std::size_t) throw (std::bad_alloc);
• void operator delete(void*) throw();
• void operator delete[](void*) throw();
• void* operator new(std::size_t, const std::nothrow_t&) throw();
• void* operator new[](std::size_t, const std::nothrow_t&) throw();
• void operator delete(void*, const std::nothrow_t&) throw();
• void operator delete[](void*, const std::nothrow_t&) throw();
Variants of built-in operator new() and delete() continue …
• inline void* operator new(std::size_t, void* __p) throw() { return __p; }
• inline void* operator new[](std::size_t, void* __p) throw() { return __p; }
• inline void operator delete (void*, void*) throw() { }
• inline void operator delete[](void*, void*) throw() { }
End of Presentation . . .