using a new_handler

D

desktop

I have made the following new_handler that I set in main:

/* ================== new_handler ================== */
void no_mem() {
std::cerr << "out of memory\n";
throw std::bad_alloc();
std::exit(1);
}

void init(int length, int* data) {

try {
data = new int [length];
}
catch(std::bad_alloc){
std::cerr<< "out of memory\n";

}

}


int main() {
// Initialize the new_handler.
std::set_new_handler(&no_mem);

int* data;
int i = 4;
init(i,data);
return 0;

}

But is it necessary to catch the exception in "init" or will it also be
caught by the new_handler?
 
J

James Kanze

I have made the following new_handler that I set in main:

Two comments:
/* ================== new_handler ================== */
void no_mem() {
std::cerr << "out of memory\n";

Id this is the first use of std::cerr, there's a certain
probability that it will try to allocate memory. Which may lead
to endless recursion.

The usual technique when you want to do something like this is
to pre-allocate a hopefully big enough block, and free it in the
handler, immediately before using cerr.
throw std::bad_alloc();
std::exit(1);

And of course, since you've thrown an exception in the preceding
line, this line will never be reached. (From experience, the
"usual" new handler is something like:

void
no_mem()
{
delete [] preallocated ;
std::cerr << "Out of memory" << std::endl ;
abort() ;
}
void init(int length, int* data) {

try {
data = new int [length];
}
catch(std::bad_alloc){
std::cerr<< "out of memory\n";
}
}
int main() {
// Initialize the new_handler.
std::set_new_handler(&no_mem);
int* data;
int i = 4;
init(i,data);
return 0;

}
But is it necessary to catch the exception in "init" or will it also be
caught by the new_handler?

In your case, the new handler is throwing the exception, not
catching it. The new handler is called before the exception is
thrown, and will normally not see it.
 
D

desktop

James said:
I have made the following new_handler that I set in main:

Two comments:
/* ================== new_handler ================== */
void no_mem() {
std::cerr << "out of memory\n";

Id this is the first use of std::cerr, there's a certain
probability that it will try to allocate memory. Which may lead
to endless recursion.

The usual technique when you want to do something like this is
to pre-allocate a hopefully big enough block, and free it in the
handler, immediately before using cerr.
throw std::bad_alloc();
std::exit(1);

And of course, since you've thrown an exception in the preceding
line, this line will never be reached. (From experience, the
"usual" new handler is something like:

void
no_mem()
{
delete [] preallocated ;
std::cerr << "Out of memory" << std::endl ;
abort() ;
}
void init(int length, int* data) {

try {
data = new int [length];
}
catch(std::bad_alloc){
std::cerr<< "out of memory\n";
}
}
int main() {
// Initialize the new_handler.
std::set_new_handler(&no_mem);
int* data;
int i = 4;
init(i,data);
return 0;

}
But is it necessary to catch the exception in "init" or will it also be
caught by the new_handler?

In your case, the new handler is throwing the exception, not
catching it. The new handler is called before the exception is
thrown, and will normally not see it.

--
James Kanze (Gabi Software) email: (e-mail address removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Ok the example I made was more or less based on Bjarne Stroustrup's
example on page 129 i the C++ Programming Language. His new_handler
looks like this:

void out_of_store() {
cerr << "operator new failed: out of store\n";
throw bad_alloc();
}

He also show a function that uses new:

void f() {
try{
for(;;) new char[10000];
}
catch(bad_alloc) {
cerr << "Memory exhausted!\n";
}
}

But I don't see why the out_of_store() function is needed if all
functions that uses new just makes sure to catch bad_alloc.

Would it not make more sense to make a new_handler that catches
bad_alloc and then omit the try/catch in all functions using new, since
the new_handler takes care of the catch for all new calls?
 
J

James Kanze

Ok the example I made was more or less based on Bjarne Stroustrup's
example on page 129 i the C++ Programming Language. His new_handler
looks like this:
void out_of_store() {
cerr << "operator new failed: out of store\n";
throw bad_alloc();

}
He also show a function that uses new:
void f() {
try{
for(;;) new char[10000];
}
catch(bad_alloc) {
cerr << "Memory exhausted!\n";
}
}
But I don't see why the out_of_store() function is needed if all
functions that uses new just makes sure to catch bad_alloc.

Probably, his goal was only to show how you can create a new
handler, not what it might be used for in practice. In this
exact example, for example, there really isn't much point in
using a new handler (and it's likely to fail anyway, at least on
some implementations, because cerr will also try to allocate
memory).
Would it not make more sense to make a new_handler that catches
bad_alloc and then omit the try/catch in all functions using new, since
the new_handler takes care of the catch for all new calls?

That's what I usually do. For various reasons, it's not
generally possible to reliably recover from insufficient memory.
My applications (large servers) generally run on dedicated
machines, with what should be sufficient memory; if memory runs
out, it's almost certainly because there is a memory leak, and
of course, at that point, recovery is impossible. But more
generally, not all systems reliably report out of memory, and
even less will allow you to intervene if you run out of memory
increasing the size of the stack, or something like that. So
you reserve a bit on the side, and install a new handler which
logs the problem, and aborts.
 
J

James Kanze

Ok the example I made was more or less based on Bjarne Stroustrup's
example on page 129 i the C++ Programming Language. His new_handler
looks like this:
void out_of_store() {
cerr << "operator new failed: out of store\n";
throw bad_alloc();

}
He also show a function that uses new:
void f() {
try{
for(;;) new char[10000];
}
catch(bad_alloc) {
cerr << "Memory exhausted!\n";
}
}
But I don't see why the out_of_store() function is needed if all
functions that uses new just makes sure to catch bad_alloc.

Probably, his goal was only to show how you can create a new
handler, not what it might be used for in practice. In this
exact example, for example, there really isn't much point in
using a new handler (and it's likely to fail anyway, at least on
some implementations, because cerr will also try to allocate
memory).
Would it not make more sense to make a new_handler that catches
bad_alloc and then omit the try/catch in all functions using new, since
the new_handler takes care of the catch for all new calls?

That's what I usually do. For various reasons, it's not
generally possible to reliably recover from insufficient memory.
My applications (large servers) generally run on dedicated
machines, with what should be sufficient memory; if memory runs
out, it's almost certainly because there is a memory leak, and
of course, at that point, recovery is impossible. But more
generally, not all systems reliably report out of memory, and
even less will allow you to intervene if you run out of memory
increasing the size of the stack, or something like that. So
you reserve a bit on the side, and install a new handler which
logs the problem, and aborts.
 
J

James Kanze

Ok the example I made was more or less based on Bjarne Stroustrup's
example on page 129 i the C++ Programming Language. His new_handler
looks like this:
void out_of_store() {
cerr << "operator new failed: out of store\n";
throw bad_alloc();

}
He also show a function that uses new:
void f() {
try{
for(;;) new char[10000];
}
catch(bad_alloc) {
cerr << "Memory exhausted!\n";
}
}
But I don't see why the out_of_store() function is needed if all
functions that uses new just makes sure to catch bad_alloc.

Probably, his goal was only to show how you can create a new
handler, not what it might be used for in practice. In this
exact example, for example, there really isn't much point in
using a new handler (and it's likely to fail anyway, at least on
some implementations, because cerr will also try to allocate
memory).
Would it not make more sense to make a new_handler that catches
bad_alloc and then omit the try/catch in all functions using new, since
the new_handler takes care of the catch for all new calls?

That's what I usually do. For various reasons, it's not
generally possible to reliably recover from insufficient memory.
My applications (large servers) generally run on dedicated
machines, with what should be sufficient memory; if memory runs
out, it's almost certainly because there is a memory leak, and
of course, at that point, recovery is impossible. But more
generally, not all systems reliably report out of memory, and
even less will allow you to intervene if you run out of memory
increasing the size of the stack, or something like that. So
you reserve a bit on the side, and install a new handler which
logs the problem, and aborts.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top