exception handler for bad alloc exception.

Im a newbie at c++ was confused on how to put a exception handler in here to catch a bad alloc exception if the user attempts to allocate an array object and insufficient memory is available.

here is what i have
class array 
{ 
 public: 
  
array( int = 1 ); 
  
// other functions not needed for this assignment 
 private: 
  
int*  elts; 
  
int  count; 
}; 
 
array::array( int sz ) 
{ 
 count = sz; 
 elts  = new int[ count ]; 
} 
 
int main( ) 
{ 
 array* ptr[10]; 
 
 for ( int i = 0; i < 10; i++ ) 
 { 
  
ptr[i] = new array( 100000000L ); 
 } 
}

Open in new window

chetmunk700Asked:
Who is Participating?
 
phoffricCommented:
You could add #include <exception> and then catch the bad_alloc exception. When your constructor throws the exception, the object, in general, is now in an incomplete state; so you should not use it as is without fixing it.
int i;

    for ( i = 0; i < 10; i++ )
    {
        try {
            ptr[i] = new array( 100000000L );
        }
        catch (bad_alloc) {

                cout << "bad_alloc: i = " << i << endl;
                break;
        }
    }

Open in new window

0
 
theKashyapCommented:
Do note that there 3 overloads of new available usually.

void* operator new (std::size_t size) throw (std::bad_alloc);
First one, which is used by default by everyone throws bad_alloc on error.

There are 2 others.
void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw();
This one returns NULL instead of throwing bad_alloc in case it fails to allocate memory.

void* operator new (std::size_t size, void* ptr) throw();
This is the third/last one. It's useful when you're dealing with large number of objects. It improves the performance many fold when used in correct usecases (your case is one such case). An example here.

Given below your code modified to use placement new. It's ~25 times faster for 100 array object of 5000000 ints each.

Examples of all 3 new:
using namespace std;

class array {
public:
    array( const int = 1);
    array( const int, void*& buffer );

// other functions not needed for this assignment
private:
    int*  elts;
    int  count;
};

array::array( const int sz ) {
    try {
        elts  = new int[ sz ];
        count = sz;
    } catch (bad_alloc) {
        cout << "array::array() -- Failed to allocate: " << sz << endl;
    }
}

array::array( const int sz, void*& buffer ) {
    // cout << "array::array() -- entry sz = " << sz << endl << "buffer = " << buffer << endl;
    // As placement new does NOT allocate memory it never fails unless the c'tor
    // of the type throws an error.
    elts  = new (buffer) int[ sz ];

    // forward the ptr beyond the used memory, so it points to
    // the remainder of free memory.
    (int*&)buffer += (sz * sizeof(int));

    count = sz;
}

int main( ) {
    const int ARR_SIZE = 5000000;
    const int LOOP_SIZE = 100;
    array* ptr[LOOP_SIZE];

    void* my_buffer = malloc(ARR_SIZE * LOOP_SIZE * sizeof(int));
    if ( NULL == my_buffer ) {
        cout << "Failed to allocate buffer." << endl;
        return 1;
    }

    for ( int i = 0; i < LOOP_SIZE; i++ ) {
        ptr[i] = new array( ARR_SIZE, my_buffer );
    }

    // either use free() to do a bulk free or use the normal delete
    // operator if you want to deallocated element by element.

    return 0;
}

Open in new window


A good reference: http://www.cplusplus.com/reference/std/new/operator%20new/
0
 
evilrixSenior Software Engineer (Avast)Commented:
Just to note that you should always catch exceptions by reference (const normally) and not value!

catch (bad_alloc  const &)

Open in new window


When you catch by value you create a new copy of the exception. Also if the exception is caught by value and you happen to catch a superclass you will slice the object if the original exception was a subclass.
0
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
evilrixSenior Software Engineer (Avast)Commented:
Oh, and one other thing - to save you messing around with new and delete (and possibly leaking memory) why don't you just use a vector?

http://www.cplusplus.com/reference/stl/vector/
0
 
theKashyapCommented:
@evilrix: Think it's an assignment to learn new operator.
0
 
phoffricCommented:
>> you should always catch exceptions by reference (const normally) and not value!
>> catch (bad_alloc  const &)
My reference book says:
     catch (bad_alloc)

It looks like for bad_alloc, this is Ok.

>> Also if the exception is caught by value and you happen to catch a superclass you will slice the object if the original exception was a subclass.
This remark can be generalized as a legitimate concern in discussing passing function arguments, but we still can pass by value for specific situations.
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> It looks like for bad_alloc, this is Ok.
It's still creating an unnecessary copy :)

>> but we still can pass by value for specific situations.
Sure you can but in the case of exceptions the standard ones are polymorphic and if you catch by value and not by exception you will slice. For example, there is nothing to stop a library sub-classing bad_alloc and throwing a sub-class version of it. Boost often subclasses standard exceptions.

In the end, it is just something for the asker to be aware of.
0
 
phoffricCommented:
>> It's still creating an unnecessary copy :)
   catch (bad_alloc  const &)
   catch (bad_alloc)
Something is being copied in both cases. Not much of a difference in quantity copied.
0
 
trinitrotolueneDirector - Software EngineeringCommented:
just another point to be noted since I saw some code using malloc in this thread.

Do not mix malloc and new in your program and if you must do it ensure that memory allocated using malloc is freed using free() and not delete. Likewise for new, only use delete to release memory allocated using new
0
 
evilrixSenior Software Engineer (Avast)Commented:
>Something is being copied in both cases.
In the case of catching by reference the reference is bound to the thrown object, in the case of the second the copy constructor will be called.
0
 
evilrixSenior Software Engineer (Avast)Commented:
0
 
theKashyapCommented:
0
 
evilrixSenior Software Engineer (Avast)Commented:
theKashyap,

Please note that your article is not yet published.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.