|
-
April 5th, 2006, 04:57 PM
#1
Catching bad_alloc Exceptions
Hello.
After having used Visual C++ version 6 for a number of years, and checking for new returning NULL, I am now starting to code with try-catch blocks.
(I know about the STL and <vector> class, but I’d like to master the try-catch approach too, so please bear with me).
I am wondering: what exactly is thrown with a bad_alloc exception? Is it a memory address? An integer? . . .
The reason I ask is because I am trying to write a small program that dynamically creates several arrays. All the examples I have found so far show it to handle an exception when allocating a single array. However, I am finding it tricky to code for multiple arrays. Here’s a code snippet for the try block (say, two 2D arrays, and one hundred 1D arrays):
Code:
try { // Beginning of try block
b1 = new double[mDim];
A = new double*[mDim]; //Allocate space for pointers to rows of A matrix
for (i = 0; i < mDim; i++) {
A[i] = new double[mDim]; //Allocate space for columns of A matrix
}//End for i
b2 = new double[mDim];
b3 = new double[mDim];
b4 = new double[mDim];
D = new double*[mDim]; //Allocate space for pointers to rows of D matrix
for (i = 0; i < mDim; i++) {
D[i] = new double[mDim]; //Allocate space for columns of D matrix
}//End for i
b5 = new double[mDim];
. . .
b100 = new double[mDim];
} // End of try block
How do I code the catch block? If a bad_alloc exception is thrown, I would have to deallocate all arrays created up to that point, wouldn’t I? Something similar to the following might have to be done (assumes all pointers initialized to NULL when first defined):
Code:
catch (bad_alloc& xa) { // Catch block, for allocation exceptions
cerr << "In catch block, so an allocation failed.\n”;
if (b1) delete[] b1;
if (A)
{//count down from the highest value of i that we reached before the exception
for (; i > 0; --i) {
delete[] A[i];
}
delete[] A;
}
if (b2) delete[] b2;
if (b3) delete[] b3;
if (b4) delete[] b4;
if (D)
{//count down from the highest value of i that we reached before the exception
for (; i > 0; --i) {
delete[] D[i];
}
delete[] A;
}
if (b5) delete[] b5;
. . .
if (b100) delete[] b100;
return 0;
} // End of catch block
This approach would get very tedious, especially if many more arrays are involved. If bad_alloc was an integer, and the deallocation sequence was ordered properly, the try block could use a switch statement to indicate which array caused the exception to be thrown, and then drop through the rest of the switch statements. Can this be done?
Your help is much appreciated.
David
-
April 5th, 2006, 05:42 PM
#2
Re: Catching bad_alloc Exceptions
 Originally Posted by DavidB
(assumes all pointers initialized to NULL when first defined):
You can delete NULL-pointers, so if all your pointers are initialized to NULL when defined you don't need all those:
Code:
if(ptr)
delete ptr;
This is enough:
Anyway, I assume that you have a some destructor/finalizing method that clean up your pointers. What if you call this function from within the catch? That would maybe save you from a lot of work.
- petter
-
April 6th, 2006, 03:44 AM
#3
Re: Catching bad_alloc Exceptions
A bad_alloc gives you no information. Not even the number of bytes you tried to allocate.
If a bad_alloc failure happened on a small allocation then you have a major memory problem and your best bet is to terminate as cleanly as possible. If it's a critical application / server then you should probably have some already-allocated backup memory that you can use to launch a duplicate server and log any errors etc while yours restarts.
There are occasions where you might get a bad_alloc because of an attempt to allocate a very large amount of memory. You might even do this on purpose to test the capacity of your system - attempt to allocate larger and larger blocks to see how far you go before you fail. Such a function may be useful to give scalability, for example if you want a large memory cache and are deciding how much you can use. (Perhaps half of the amount available before the bad_alloc occurred).
Code:
size_t capacity = 1;
unsigned char * block;
try
{
while ( capacity )
{
block = new unsigned char[capacity];
delete [] block;
capacity *= 2;
}
// block ends if it wraps round and never fails
std::cout << "new never failed " << std::endl;
}
catch ( const bad_alloc & )
{
std::cout << "new failed on " << capacity << std::endl;
}
Note this may not work on Linux which does not throw bad_alloc on a failed allocation, but simply blows up later. On this occasion you are not trying to use the memory so it probably won't blow up but you'll get "new never failed".
-
April 6th, 2006, 06:11 AM
#4
Re: Catching bad_alloc Exceptions
David, you need smart pointers to handle so many dynamic allocations otherwise the code will look so messy and it is very prone to getting leaks. And still better using vectors - but as you mention you want to keep that aside for some self learning read ahead.
As for finding out which allocation failed - After initializing all the pointers to NULL and then calling the allocation routines and inside the catch block you do something like this:
Code:
if (ptr1){
//send out a message/write a log file/write to cout that allocation for ptr1 was done successfully.
cout << "allocation for ptr1 was done successfully ";
delete[] ptr1;
ptr1 = NULL;
}
if (ptr2){
cout << "allocation for ptr2 was done successfully " ;
delete[] ptr2;
ptr2 = NULL;
}
To get to know how much was being allocated and what size caused the failure - NMTop40's suggestion would help you. Regards.
Can you help me with my homework assignment?, Before you post!, Use code tags, How to post!, Codeguru technical FAQs, C++ FAQ Lite, Stroustrup: C++ Style and Technique FAQ, Guru of the Week, Comeau C and C++ FAQs, Comeau C++ Templates FAQs, CUJ @ DDJ, Spam threshold
My Blogs : Learning C++ is fun | Abnegator's reflections
Open Threads : C++ Aha! Moments | Nature of work in C++?
-
April 6th, 2006, 09:51 AM
#5
Re: Catching bad_alloc Exceptions
 Originally Posted by exterminator
David, you need smart pointers to handle so many dynamic allocations otherwise the code will look so messy and it is very prone to getting leaks. And still better using vectors - but as you mention you want to keep that aside for some self learning read ahead.
Strange that something that complicated would be for self learning. This would have sufficed:
Code:
double *pdouble1 = 0;
double *pdouble2 = 0;
int main()
{
try
{
pdouble1 = new double [100000];
pdouble2 = new double [100000];
delete [] pdouble1;
delete [] pdouble2;
}
catch (const std::bad_alloc& )
{
// whatever
}
}
David, one word of advice -- please use vectors for what you're trying to do. If you want to learn how try/catch and std::bad_alloc work, you don't need to write (or mess up) an entire application for learning purposes (see the code above).
Regards,
Paul McKenzie
-
April 6th, 2006, 09:54 AM
#6
Re: Catching bad_alloc Exceptions
In Paul's code, you would have to delete[] the first pointer in the catch block if the second one threw.
-
April 10th, 2006, 01:22 PM
#7
Re: Catching bad_alloc Exceptions
 Originally Posted by Paul McKenzie
David, one word of advice -- please use vectors for what you're trying to do. If you want to learn how try/catch and std::bad_alloc work, you don't need to write (or mess up) an entire application for learning purposes (see the code above).
Regards,
Paul McKenzie
Thanks for the advice, Paul; I intend to take it, and will edit my code to use vectors.
Some background:
I have translated several numerical linear algebra routines from FORTRAN to C++ to Javascript and posted them online. Many people have contacted me to request the C++ source code, and I intend to supply it by posting it online. However, I would first like to polish it up (my code still uses the check for new returning NULL).
In the course of browsing several forums, reading books, etc., concrete examples of dynamic arrays for numerical applications seemed pretty hard to find—so I decided to post my own:
http://www.akiti.ca/DynamicArraysIntro.html
(An example using vectors will be written and posted soon.)
These pages will remain up; if anybody learns from them, wonderful. And if you have any suggestions for how the code might be further polished, please feel free to offer constructive criticism.
Once these pages are finalized, I will continue with my original goal: re-coding the existing routines using vectors (and then posting that code online too).
Regards,
David
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|