Home arrow C++ Programming arrow new & delete for arrays

Language Translator

Hacking Zone

Hacking Tools
Attacking

Configure Windows

Windows Configuration

Novels

Mix Novels

Human Personality

Body Language
new & delete for arrays PDF Print E-mail
Written by Hemanshu Patel   
Monday, 22 October 2007
Article Index
new & delete for arrays
Page 2
Page 3
Page 4

Running out of storage

What happens when the operator new( ) cannot find a contiguous block of storage large enough to hold the desired object? A special function called the new-handler is called. Or rather, a pointer to a function is checked, and if the pointer is nonzero, then the function it points to is called.

The default behavior for the new-handler is to throw an exception, a subject covered in Volume 2. However, if you’re using heap allocation in your program, it’s wise to at least replace the new-handler with a message that says you’ve run out of memory and then aborts the program. That way, during debugging, you’ll have a clue about what happened. For the final program you’ll want to use more robust recovery.

You replace the new-handler by including new.h and then calling set_new_handler( ) with the address of the function you want installed:

//: C13:NewHandler.cpp
// Changing the new-handler
#include <iostream>
#include <cstdlib>
#include <new>
using namespace std;

int count = 0;

void out_of_memory() {
cerr << "memory exhausted after " << count
<< " allocations!" << endl;
exit(1);
}

int main() {
set_new_handler(out_of_memory);
while(1) {
count++;
new int[1000]; // Exhausts memory
}
} ///:~

The new-handler function must take no arguments and have a void return value. The while loop will keep allocating int objects (and throwing away their return addresses) until the free store is exhausted. At the very next call to new, no storage can be allocated, so the new-handler will be called.

The behavior of the new-handler is tied to operator new( ), so if you overload operator new( ) (covered in the next section) the new-handler will not be called by default. If you still want the new-handler to be called you’ll have to write the code to do so inside your overloaded operator new( ).

Of course, you can write more sophisticated new-handlers, even one to try to reclaim memory (commonly known as a garbage collector). This is not a job for the novice programmer.

 

Overloading new & delete

When you create a new-expression, two things occur. First, storage is allocated using the operator new( ), then the constructor is called. In a delete-expression, the destructor is called, then storage is deallocated using the operator delete( ). The constructor and destructor calls are never under your control (otherwise you might accidentally subvert them), but you can change the storage allocation functions operator new( ) and operator delete( ).

The memory allocation system used by new and delete is designed for general-purpose use. In special situations, however, it doesn’t serve your needs. The most common reason to change the allocator is efficiency: You might be creating and destroying so many objects of a particular class that it has become a speed bottleneck. C++ allows you to overload new and delete to implement your own storage allocation scheme, so you can handle problems like this.

Another issue is heap fragmentation. By allocating objects of different sizes it’s possible to break up the heap so that you effectively run out of storage. That is, the storage might be available, but because of fragmentation no piece is big enough to satisfy your needs. By creating your own allocator for a particular class, you can ensure this never happens.

In embedded and real-time systems, a program may have to run for a very long time with restricted resources. Such a system may also require that memory allocation always take the same amount of time, and there’s no allowance for heap exhaustion or fragmentation. A custom memory allocator is the solution; otherwise, programmers will avoid using new and delete altogether in such cases and miss out on a valuable C++ asset.

When you overload operator new( ) and operator delete( ), it’s important to remember that you’re changing only the way raw storage is allocated. The compiler will simply call your new instead of the default version to allocate storage, then call the constructor for that storage. So, although the compiler allocates storage and calls the constructor when it sees new, all you can change when you overload new is the storage allocation portion. (delete has a similar limitation.)

When you overload operator new( ), you also replace the behavior when it runs out of memory, so you must decide what to do in your operator new( ): return zero, write a loop to call the new-handler and retry allocation, or (typically) throw a bad_alloc exception (discussed in Volume 2, available at www.BruceEckel.com).

Overloading new and delete is like overloading any other operator. However, you have a choice of overloading the global allocator or using a different allocator for a particular class.

 

Overloading global new & delete

This is the drastic approach, when the global versions of new and delete are unsatisfactory for the whole system. If you overload the global versions, you make the defaults completely inaccessible – you can’t even call them from inside your redefinitions.

The overloaded new must take an argument of size_t (the Standard C standard type for sizes). This argument is generated and passed to you by the compiler and is the size of the object you’re responsible for allocating. You must return a pointer either to an object of that size (or bigger, if you have some reason to do so), or to zero if you can’t find the memory (in which case the constructor is not called!). However, if you can’t find the memory, you should probably do something more informative than just returning zero, like calling the new-handler or throwing an exception, to signal that there’s a problem.

The return value of operator new( ) is a void*, not a pointer to any particular type. All you’ve done is produce memory, not a finished object – that doesn’t happen until the constructor is called, an act the compiler guarantees and which is out of your control.

The operator delete( ) takes a void* to memory that was allocated by operator new. It’s a void* because operator delete only gets the pointer after the destructor is called, which removes the object-ness from the piece of storage. The return type is void.

Here’s a simple example showing how to overload the global new and delete:

//: C13:GlobalOperatorNew.cpp
// Overload global new/delete
#include <cstdio>
#include <cstdlib>
using namespace std;

void* operator new(size_t sz) {
printf("operator new: %d Bytes\n", sz);
void* m = malloc(sz);
if(!m) puts("out of memory");
return m;
}

void operator delete(void* m) {
puts("operator delete");
free(m);
}

class S {
int i[100];
public:
S() { puts("S::S()"); }
~S() { puts("S::~S()"); }
};

int main() {
puts("creating & destroying an int");
int* p = new int(47);
delete p;
puts("creating & destroying an s");
S* s = new S;
delete s;
puts("creating & destroying S[3]");
S* sa = new S[3];
delete []sa;
} ///:~

Here you can see the general form for overloading new and delete. These use the Standard C library functions malloc( ) and free( ) for the allocators (which is probably what the default new and delete use as well!). However, they also print messages about what they are doing. Notice that printf( ) and puts( ) are used rather than iostreams. This is because when an iostream object is created (like the global cin, cout, and cerr), it calls new to allocate memory. With printf( ), you don’t get into a deadlock because it doesn’t call new to initialize itself.

In main( ), objects of built-in types are created to prove that the overloaded new and delete are also called in that case. Then a single object of type S is created, followed by an array of S. For the array, you’ll see from the number of bytes requested that extra memory is allocated to store information (inside the array) about the number of objects it holds. In all cases, the global overloaded versions of new and delete are used.

  

 
< Prev   Next >
Your Ad Here

Donate us!!

Enter Amount:

RSS socialnet

Add to MyYahoo!
Subscribe in NewsGator Online
Add to Newsburst
Add to Google
Add to My AOL
Add to Pluck
Subscribe in FeedLounge
Add to Windows Live
Add to NetVibes
Subscribe in Rojo
Subscribe in Bloglines
Add to MyMSN
Add to Plusmo for your cellphone
Add to PageFlakes
Add to Technorati
Add to BlinkBits