Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 654
  • Last Modified:

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

0
chetmunk700
Asked:
chetmunk700
  • 6
  • 3
  • 3
  • +1
1 Solution
 
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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
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

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 6
  • 3
  • 3
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now