throwing out of memory exception in c++ doesnt work

S

Stephan

why does the following code not work????
after compiling and running it will just say killed after all my memory
filled up
any suggestions?


#include <iostream>
using namespace std;

void out_of_mem() {
cout << "problem\n";
}

// void ?
int main() {

set_new_handler(out_of_mem);

while(1) {
int * tst = new int[1024];
if (!tst)
cout << "problem\n";
}
 
L

Leor Zolman

why does the following code not work????
after compiling and running it will just say killed after all my memory
filled up
any suggestions?

#include <iostream>
using namespace std;

void out_of_mem() {
cout << "problem\n";
}

// void ?
int main() {

set_new_handler(out_of_mem);

while(1) {
int * tst = new int[1024];
if (!tst)
cout << "problem\n";
}


The subject of your post is "throwing out of memory exception in c++
doesn't work", but you've done precisely what it takes to /prevent/ such an
exception from ever being thrown: you've created and installed a
new_handler that doesn't follow the rules of what a new_handler should do,
which is one of the following ( I'm plagiarizing this from Dinkumware's C++
Reference):

make more storage available for allocation and then return
call either abort() or exit(int)
throw an object of type bad_alloc

If you've got a reasonably healthy quantity of virtual memory available,
though, it may take quite a while to thrash itself to exhaustion before it
reaches the point of calling your new_handler, so let's speed things up a
bit and add some exception handling:

#include <iostream>
#include <exception>
#include <stdexcept>

using namespace std;

void out_of_mem() {
cerr << "in out_of_mem: problem\n";
throw bad_alloc();
}

int main() {

set_new_handler(out_of_mem);

try {
while(1) {
cout << "Top of loop" << endl;
int * tst = new int[800000000]; // make this too much!
if (!tst)
cout << "end of loop: problem\n";
}
}
catch (const exception &e)
{
cerr << "Caught: " << e.what() << endl;
exit(1);
}

return 0; // not likely to get here!
}


Output (MSVC 7.1):

Top of loop
in out_of_mem: problem
Caught: bad allocation


So after you "handle" the exceptions and make sure your new_handler does
one of the right things, you'll still have the virtual memory thrashing
problem to contend with. I can't help you there, but you definitely want to
do a better job of avoiding memory leaks than your test program did (yeah
yeah, just kidding), and perhaps just "know" how much memory you can
allocate before the thrashing commences and try to keep track of what
you've allocated.

Good luck,
-leor

Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
C++ users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html
 
S

Stephan

The subject of your post is "throwing out of memory exception in c++
doesn't work", but you've done precisely what it takes to /prevent/ such an
exception from ever being thrown: you've created and installed a
new_handler that doesn't follow the rules of what a new_handler should do,
which is one of the following ( I'm plagiarizing this from Dinkumware's C++
Reference):

make more storage available for allocation and then return
call either abort() or exit(int)
throw an object of type bad_alloc

If you've got a reasonably healthy quantity of virtual memory available,
though, it may take quite a while to thrash itself to exhaustion before it
reaches the point of calling your new_handler, so let's speed things up a
bit and add some exception handling:

#include <iostream>
#include <exception>
#include <stdexcept>

using namespace std;

void out_of_mem() {
cerr << "in out_of_mem: problem\n";
throw bad_alloc();
}

int main() {

set_new_handler(out_of_mem);

try {
while(1) {
cout << "Top of loop" << endl;
int * tst = new int[800000000]; // make this too much!
if (!tst)
cout << "end of loop: problem\n";
}
}
catch (const exception &e)
{
cerr << "Caught: " << e.what() << endl;
exit(1);
}

return 0; // not likely to get here!
}


Output (MSVC 7.1):

Top of loop
in out_of_mem: problem
Caught: bad allocation


So after you "handle" the exceptions and make sure your new_handler does
one of the right things, you'll still have the virtual memory thrashing
problem to contend with. I can't help you there, but you definitely want to
do a better job of avoiding memory leaks than your test program did (yeah
yeah, just kidding), and perhaps just "know" how much memory you can
allocate before the thrashing commences and try to keep track of what
you've allocated.

Good luck,
-leor

Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
C++ users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html

thanks for the quick post!!
and your code seems to make a lot more sense now, and the exception gets
thrown, when allocating the array of ints, but I am trying to allocate a
couple small int arrays, and than it will just say Killed and I have no
ide why it didnt go into the handler.
thanks for the good try block/catch block example (although I have no idea
where the exception data type comes from, and I guess I want to avoid it?)
thx
Stephan
 
L

Leor Zolman

thanks for the quick post!!
and your code seems to make a lot more sense now, and the exception gets
thrown, when allocating the array of ints, but I am trying to allocate a
couple small int arrays, and than it will just say Killed and I have no
ide why it didnt go into the handler.

If you're not allocating much memory and your program crashes, I doubt the
crash is related to exhaustion of the free store! Pointer bug? Have a
debugger you can fire up and trace through the program with? Why do you
think the issue is dynamic-memory-allocation-failure related?
thanks for the good try block/catch block example (although I have no idea
where the exception data type comes from, and I guess I want to avoid it?)

You mean bad_alloc? That's from <stdexcept> ("Standard exceptions"). If
you're not all that familiar with the exception handling mechanism and/or
debugging techniques, I highly recommend the first few chapters of
Eckel/Allison's _Thinking in C++ Volume 2_, a free download at
www.mindview.net

Good luck,
-leor
thx
Stephan

Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
C++ users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html
 
S

Stephan

On Mon, 01 Mar 2004 05:12:56 GMT, Stephan

If you're not allocating much memory and your program crashes, I doubt the
crash is related to exhaustion of the free store! Pointer bug? Have a
debugger you can fire up and trace through the program with? Why do you
think the issue is dynamic-memory-allocation-failure related?

gdb just tells me:
Program terminated with signal SIGKILL, Killed.
I didnt kill it and gdb doesnt report a line number, and gtkrellm shows
that my memory is filling up until the SIGKILL interrupts.
You mean bad_alloc? That's from <stdexcept> ("Standard exceptions"). If
you're not all that familiar with the exception handling mechanism
and/or debugging techniques, I highly recommend the first few chapters
of Eckel/Allison's _Thinking in C++ Volume 2_, a free download at
www.mindview.net

Good luck,
-leor


Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix C++
users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html
I am pretty familiar with the above, and I meant the actual exception data
type you wrote here:
catch (const exception &e)
I think this is the type for any OS thrown exceptions, since you can throw
your own int, char, whatever ones. I guess I answered my own question.

However I am still unsure about why I get a SIGKILL ! If I leave your try
and catch block out and dont throw the bad_alloc(), I ll be stuck in an
endless loop but I can't even see that more memory is used in gtkrellm,
which shows how much memory is currently in use.
thanks
stephan
 
L

Leor Zolman

gdb just tells me:
Program terminated with signal SIGKILL, Killed.
I didnt kill it and gdb doesnt report a line number, and gtkrellm shows
that my memory is filling up until the SIGKILL interrupts.

Good, intuitive debuggers can be hard to find on Unix...but there's always
good 'ole cerr. As a last resort I begin putting in trace statements. There
are some great tricks for doing that sort of thing in the Eckel/Allison
book I cited. You need a better handle on where the code is when it
crashes.
I am pretty familiar with the above, and I meant the actual exception data
type you wrote here:
I think this is the type for any OS thrown exceptions, since you can throw
your own int, char, whatever ones. I guess I answered my own question.

Yeah, basically all standard exceptions derive from "exception"; in this
case I did that to gain access to the what() member function. If I didn't
care about that, I would probably just have used catch(...)
-leor
However I am still unsure about why I get a SIGKILL ! If I leave your try
and catch block out and dont throw the bad_alloc(), I ll be stuck in an
endless loop but I can't even see that more memory is used in gtkrellm,
which shows how much memory is currently in use.
thanks
stephan

Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
C++ users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html
 
C

Chris \( Val \)

| On Mon, 01 Mar 2004 03:45:44 GMT, Stephan
|
| >why does the following code not work????
| >after compiling and running it will just say killed after all my memory
| >filled up
| >any suggestions?
| >
| >#include <iostream>
| >using namespace std;
| >
| >void out_of_mem() {
| > cout << "problem\n";
| >}
| >
| >// void ?
| >int main() {
| >
| > set_new_handler(out_of_mem);
| >
| > while(1) {
| > int * tst = new int[1024];
| > if (!tst)
| > cout << "problem\n";
| > }

[snip]

C'mon Leor :).

You know that 'new' does not return '0' unless you tell it to:

int * tst = new ( std::nothrow )int[ 80000000 ];

Oh, and don't forget to break out of the 'if' statement.

Cheers.
Chris Val
 
L

Leor Zolman

| On Mon, 01 Mar 2004 03:45:44 GMT, Stephan
|
| >why does the following code not work????
| >after compiling and running it will just say killed after all my memory
| >filled up
| >any suggestions?
| >
| >#include <iostream>
| >using namespace std;
| >
| >void out_of_mem() {
| > cout << "problem\n";
| >}
| >
| >// void ?
| >int main() {
| >
| > set_new_handler(out_of_mem);
| >
| > while(1) {
| > int * tst = new int[1024];
| > if (!tst)
| > cout << "problem\n";
| > }

[snip]

C'mon Leor :).

You know that 'new' does not return '0' unless you tell it to:

int * tst = new ( std::nothrow )int[ 80000000 ];

You know, I originally was going to pursue that part of it and got
completely sidetracked by the exception behavior aspects of this...so I
stopped thinking about that code after the new operation because I figured
it would never be reached! Duh. I'm still definitely on a learning curve
when it comes to my "mental checklist" of things to look out for in these
posts!
Thanks Chris,
-leor
Oh, and don't forget to break out of the 'if' statement.

Cheers.
Chris Val

Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
C++ users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html
 
C

Chris \( Val \)

|
| | | On Mon, 01 Mar 2004 03:45:44 GMT, Stephan
| |
| | >why does the following code not work????
| | >after compiling and running it will just say killed after all my memory
| | >filled up
| | >any suggestions?
| | >
| | >#include <iostream>
| | >using namespace std;
| | >
| | >void out_of_mem() {
| | > cout << "problem\n";
| | >}
| | >
| | >// void ?
| | >int main() {
| | >
| | > set_new_handler(out_of_mem);
| | >
| | > while(1) {
| | > int * tst = new int[1024];
| | > if (!tst)
| | > cout << "problem\n";
| | > }
|
| [snip]
|
| C'mon Leor :).
|
| You know that 'new' does not return '0' unless you tell it to:
|
| int * tst = new ( std::nothrow )int[ 80000000 ];
|
| Oh, and don't forget to break out of the 'if' statement.

Actually - I just realised, this test is wrong :).

Even if we use the 'std::nothrow', it will no longer
throw 'std::bad_alloc', but rather, it will return 0,
and this will bypass 'std::set_new_handler'.

Better to avoid the 'if' expression completely, and
redesign the test case :).

# include <iostream>
# include <ostream>
# include <new>

void MyHandler()
{
std::cout << "MyHandler Called... " << std::endl;
throw std::bad_alloc();
}

int main()
{
std::set_new_handler( MyHandler );

try
{
for( int Idx( 0 ); Idx < 1000000; ++Idx )
new char[ Idx * Idx ];
}
catch( const std::bad_alloc& e )
{
std::cout << e.what() << std::endl;
}

std::cin.get();
return 0;
}

Cheers.
Chris Val
 
C

Chris \( Val \)

| On Tue, 2 Mar 2004 01:00:44 +1100, "Chris \( Val \)"

[snip]

| >int * tst = new ( std::nothrow )int[ 80000000 ];
|
| You know, I originally was going to pursue that part of it and got
| completely sidetracked by the exception behavior aspects of this...so I
| stopped thinking about that code after the new operation because I figured
| it would never be reached! Duh. I'm still definitely on a learning curve
| when it comes to my "mental checklist" of things to look out for in these
| posts!

I know the feeling, I feel like that now - need serious shut eye :).

Cheers.
Chris Val
 
L

Leor Zolman

Even if we use the 'std::nothrow', it will no longer
throw 'std::bad_alloc', but rather, it will return 0,
and this will bypass 'std::set_new_handler'.

From what I've seen while testing, the new_handler does get called, even
with the nothrow. I haven't pinned down the precise place in the Standard
that would specify this, but it does make sense...calling a handler
function isn't "throwing an exception".
Better to avoid the 'if' expression completely, and
redesign the test case :).

We've been all over the place with this, so a lesson learned would be:
choose either exception-based new failure handling, or NULL-return-based
new failure handling, but don't try to juggle both at the same time ;-)

And I'm still not convinced the OP's problem has /anything/ to do with free
store exhaustion...
-leor
# include <iostream>
# include <ostream>
# include <new>

void MyHandler()
{
std::cout << "MyHandler Called... " << std::endl;
throw std::bad_alloc();
}

int main()
{
std::set_new_handler( MyHandler );

try
{
for( int Idx( 0 ); Idx < 1000000; ++Idx )
new char[ Idx * Idx ];
}
catch( const std::bad_alloc& e )
{
std::cout << e.what() << std::endl;
}

std::cin.get();
return 0;
}

Cheers.
Chris Val

Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
C++ users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html
 
U

Unforgiven

Chris said:
Leor Zolman said:
why does the following code not work????
after compiling and running it will just say killed after all my
memory filled up
any suggestions?

#include <iostream>
using namespace std;

void out_of_mem() {
cout << "problem\n";
}

// void ?
int main() {

set_new_handler(out_of_mem);

while(1) {
int * tst = new int[1024];
if (!tst)
cout << "problem\n";
}

[snip]

C'mon Leor :).

You know that 'new' does not return '0' unless you tell it to:

int * tst = new ( std::nothrow )int[ 80000000 ];

Unless you are, like Leor (and me) using Microsoft Visual C++ .Net 2003
(7.1), in which case new does return NULL in certain situations. In fact,
new will only throw exceptions in VC++ if your program links with the
Standard C++ Library (libcp.lib) *before* it links with the Standard C
Library (libc.lib). Alternatively, you can force the throwing new behaviour
by linking with thrownew.obj.
http://msdn.microsoft.com/library/en-us/vclang/html/_pluslang_The_new_and_delete_Operators.asp
 
L

Leor Zolman

[snip]

C'mon Leor :).

You know that 'new' does not return '0' unless you tell it to:

int * tst = new ( std::nothrow )int[ 80000000 ];

Unless you are, like Leor (and me) using Microsoft Visual C++ .Net 2003
(7.1)...

Just for the record, I do use VC 7.1, but no more than I use Comeau, and
only a little bit more than I use gcc, CodeWarrior, VC6, Borland, ...

I learned while vetting out the _Effective STL_ source code (and working
with STL in general, and doing stupid template tricks such as my InitUtil
library) that choice of coding techniques cannot be based simply on "what
is the most correct", because that "most correct" style may, today, only be
supported by EDG-derivative compilers. In fact, InitUtil version 2 sat on
mothballs for about exactly one year while I waited (in vain) for compilers
to catch up with EDG, only to discover after all that time how a simple
command-line option (that I wasn't aware of) would make the code compile
and work perfectly under VC7.1. And then, with a bit of momentum going (and
with a bit of help from Dave Abrahams, among others), an additional
platform or two fell into line (or my code fell in line with the
idiosyncrasies of those platforms...)

So everyone attempting to answer questions (even as we come with new ones
of our own) faces a double-challenge: getting it right in terms of the
Standard, and making it useful in terms of whatever platform an OP may or
may not be running. Most everyone realizes this, but for the benefit of the
newer arrivals (and I'm definitely one wrt this particular group), "Your
patience and understanding are appreciated!" ;-)
-leor

Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
C++ users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html
 
P

Pete Becker

Stephan said:
and your code seems to make a lot more sense now, and the exception gets
thrown, when allocating the array of ints, but I am trying to allocate a
couple small int arrays, and than it will just say Killed and I have no
ide why it didnt go into the handler.

Most likely the insertion into cout tries to allocate from the heap,
which calls your handler again, which tries to allocate from the heap,
etc. Try using printf instead.
 
S

Stephan

Most likely the insertion into cout tries to allocate from the heap,
which calls your handler again, which tries to allocate from the heap,
etc. Try using printf instead.
printf in c++? ok i thought cout or cerr would be the preferred method,
ananyway, thx for the suggestion,
it still reports killed when commenting out any sort of output...
 
L

Leor Zolman

printf in c++? ok i thought cout or cerr would be the preferred method,
ananyway, thx for the suggestion,
it still reports killed when commenting out any sort of output...

So, Stephan, in addition to Pete's printf suggestion, what other sorts of
things have you tried over the three days since you originally posted this
question? The C++ community is waiting with bated breath for opportunities
to help, but you aren't giving us much to go on... at this point, if you
can't pare the program down to reasonably postable size or figure out a way
to debug it yourself, you might consider zipping or tar-ing up the whole
thing, making it available for download somewhere, and posting the link. I
bet someone here would probably be willing to take a stab at it...
-leor

Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
C++ users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html
 
L

Leor Zolman

So, Stephan, in addition to Pete's printf suggestion, what other sorts of
things have you tried over the three days since you originally posted this
question?

Gosh, sorry, it's actually only been a day. I forgot last month was
February! (blush)
-leor

Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
C++ users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html
 
S

Stephan

Gosh, sorry, it's actually only been a day. I forgot last month was
February! (blush)
-leor

Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
C++ users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html
awwww sorry, i was going to mention it earlier, but than people would
wonder why i posted the code in the first place. I decided to leave this
out in this program, and I might include it in the next assignment. I can
see many great applications for it, dahh :) But at this point i better
just get the work done within the smallest amount of time.
I am still very interested in this and my plans were to look into it in
the next week (I know this seems like month here).
By now I tried out most of the suggestions, and I am pondering if it is an
out of memory error that kills it (SIGKILL), which it should be, since my
mem fills up and everything gets slow and blabla, and than it is freed by
the kernel and I didnt even get the chance. I will look into this later
again. Thanks for all the thinkin on this. I havent used newsgroups much
and I am positivily surprised.
yay
Stephan
 
L

Leor Zolman

awwww sorry, i was going to mention it earlier, but than people would
wonder why i posted the code in the first place. I decided to leave this
out in this program, and I might include it in the next assignment. I can
see many great applications for it, dahh :) But at this point i better
just get the work done within the smallest amount of time.
I am still very interested in this and my plans were to look into it in
the next week (I know this seems like month here).
By now I tried out most of the suggestions, and I am pondering if it is an
out of memory error that kills it (SIGKILL), which it should be, since my
mem fills up and everything gets slow and blabla, and than it is freed by
the kernel and I didnt even get the chance. I will look into this later
again. Thanks for all the thinkin on this. I havent used newsgroups much
and I am positivily surprised.
yay
Stephan

The combination of your saying you're allocating "a couple of small int
arrays" and memory is "filling up" leads me to suspect a memory leak; in
your original code you'd allocated memory using new but never deleted it,
and I figured you were just trying to deliberately exhaust memory to test
the exception handling behavior you were asking about. Perhaps I had that
wrong? Have you checked to make sure every chunk of memory you've obtained
via new is being handed to delete before the pointer get re-used?
-leor



Leor Zolman
BD Software
(e-mail address removed)
www.bdsoft.com -- On-Site Training in C/C++, Java, Perl & Unix
C++ users: Download BD Software's free STL Error Message
Decryptor at www.bdsoft.com/tools/stlfilt.html
 
C

Chris \( Val \)

| On Tue, 2 Mar 2004 01:35:43 +1100, "Chris \( Val \)"
|
| >
| >Even if we use the 'std::nothrow', it will no longer
| >throw 'std::bad_alloc', but rather, it will return 0,
| >and this will bypass 'std::set_new_handler'.
|
| From what I've seen while testing, the new_handler does get called, even
| with the nothrow. I haven't pinned down the precise place in the Standard
| that would specify this, but it does make sense...calling a handler
| function isn't "throwing an exception".

Are you sure ?

| >Better to avoid the 'if' expression completely, and
| >redesign the test case :).
|
| We've been all over the place with this, so a lesson learned would be:
| choose either exception-based new failure handling, or NULL-return-based
| new failure handling, but don't try to juggle both at the same time ;-)

Agreed :).

| And I'm still not convinced the OP's problem has /anything/ to do with free
| store exhaustion...

Me either :).

Cheers.
Chris Val
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top