exception creating 2D Array: clean-up before re-throw in C++ - c++

I want to have a function which dynamically creates and returns a 2D array or when memory allocation fails passes the exception without information loss after cleaning up already allocated rows:
double **create (int rows, int cols)
{
double **array = new double* [rows];
for (int x=0; x<rows; x++)
{
try { array[x] = new double [cols]; }
catch (exception &e)
{
x--;
for (; x>=0; x--)
delete[] array[x]; // clean up already allocated rows
delete[] array;
throw e; // pass exception
}
for (int y=0; y<cols; y++)
array[x][y] = 0; // initialize array
}
return array;
}
So I can be sure, if create throws, there is no memory leak. But can I be sure, that the passed exception e is "the same" as if directy thrown by new and not catched?
E.g.
int main ()
{
double **d;
try { d = create (HUGE_x, HUGE_y); }
catch (exception &e)
{
// 1. e could be thrown by new double* [rows]
// e.g. if HUGE_x is already to huge
// 2. e could be thrown by throw e
// e.g. if after some rows no memory anymore
// in both cases: is e the same?
}
return 0;
}
Or is it necessary to have catch (bad_alloc &e) inside the create function? Or does it work only with catch (...) { /* do clean-up*/ throw; }? Is there the same problem as in C# with losing stack trace when re-throw is not with throw; simply?
And another, more general question:
void f () { throw Object(); } // or throw "help";
void main ()
{
try { f(); }
catch (Object &e) // or catch (char *)
{
// Where is the Object or C-String created on the stack in function f()
// since we aren't any more in function f() but we are dealing with
// references/pointers to a non-existent stack?
}
}

For exception-safe memory management, use RAII. Rather than juggling raw pointers and exception handlers, assign the resource to a class which will release it on destruction. That way, everything is cleaned up automatically if an exception is thrown.
In this case, std::vector is a suitable RAII class managing a dynamic array:
vector<vector<double>> create (int rows, int cols) {
return vector<vector<double>>(rows, vector<double>(cols));
}
(Note that it may be more efficient to represent the 2D array as a single array of size rows*cols, with accessors to provide 2D indexing into it. But that's off-topic for this question, so I won't go into tedious detail).
To answer your questions, although they're largely irrelevent if you write exception-safe code:
But can I be sure, that the passed exception e is "the same" as if directy thrown by new and not catched?
It won't be; you're throwing a new object, created by copying or moving e, with type exception.
Or is it necessary to have catch (bad_alloc &e) inside the create function?
Then you won't catch other types of exceptions. In this case, that might not a problem, but you really want to be catching all exceptions if you're going to be cleaning up like this. To reiterate: don't use exception handlers to clean up. It's very error-prone.
Or does it work only with catch (...) { /* do clean-up*/ throw; }?
That will rethrow the original object, which is what you want. (Except that you shouldn't want to be catching anything in the first place).
Is there the same problem as in C# with losing stack trace when re-throw is not with throw; simply?
Standard exceptions don't give you a stack trace anyway. If you have a custom exception type with a stack trace, then it depends on whether it generates a new one when copied/moved, or copies/moves the existing one.
Where is the Object or C-String?
The exception handling mechanism creates it somewhere (not on the stack which is about to be unwound), and destroys it once it's been handled. It's not specified exactly where it is, just how it must work.

While this question is quite old by now and has been answered adequately, I would like to add a note on rethrowing exceptions.
In standard C++11 you can retain the original exception information by rethrowing with:
std::nested_exception and std::throw_with_nested
FYI: using this, you can also generate exception backtraces, as described on StackOverflow here and here, without need for a debugger or cumbersome logging, by simply writing a proper exception handler which will rethrow nested exceptions.
Since you can do this with any derived exception class, you can add a lot of information to such a backtrace!
You may also take a look at my MWE on GitHub, where a backtrace would look something like this:
Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"

Related

Set exception on promise without using std::current_exception

In C++ reference regarding the set_exception method , the example uses std::current_exception. To do that you have to throw and catch your exception:
std::thread t([&p]{
try {
// code that may throw
throw std::runtime_error("Example");
} catch(...) {
try {
// store anything thrown in the promise
p.set_exception(std::current_exception());
// or throw a custom exception instead
// p.set_exception(std::make_exception_ptr(MyException("mine")));
} catch(...) {} // set_exception() may throw too
}
});
This throwing and catching is obviously tedious, but the method accepts a std::exception_ptr. I was wondering whether it's possible to set a specific exception directly. I imagine the problem would be that a local exception object would have lifetime issues if we pass around a pointer to its address and allocating a new exception object would leave memory leaks. Is there a way ?

What should I pass to throw?

I added a bunch of exceptions to my hash table class to deal with various issues that might come up. They are mostly constructed like this:
std::string msg = std::string("I made doodoo, some value: ") + std::tostring(value);
throw std::exception(msg.c_str());
Some of the exceptions are part of normal operation, for example there is one that says the table is full and the thing that catches it then rebuilds the table into a bigger one. I discovered that this puts a sizable dent in the performance though, I suspect its all the string construction. At the same time though, I want the exceptions to be meaningful and make sense to somebody who doesn't know what the code numbers I come up with mean. Whats a good way to deal with this?
Ideally you should be creating custom exception classes from std::exception. That way when you create your catch blocks, you can have a specific catch for each of your exceptions. Example:
class MyException; // Inherits from std::exception.
class MyOtherException; // Inherits from std::exception.
void foo()
{
if (bar)
throw MyException();
if (baz)
throw MyOtherException();
// do stuff.
}
int main()
{
try
{
foo();
}
catch(const MyException &ex)
{
// Handle MyException.
}
catch (const MyOtherException &ex)
{
// Handle MyOtherException.
}
}
Creating your own exception classes affords you a lot more flexibility because it allows you to attach additional information to your exceptions, as well as handling different exception types as described above.
class MyException : public std::exception
{
private:
std::string m_description;
int m_userId;
public:
MyException(const std::string &errorDescription = "Unhandled exception", const int userId) :
m_description(errorDescription),
m_userId(userId)
{
}
int get_user_id() const
{
return m_userId;
}
virtual const char *what() const
{
return m_description.c_str();
}
}
The main problem with your code (at least how you described it) however is that you seem to be controlling your program flow with exceptions. Exceptions are not designed to be fast constructs, they're designed for exceptional cases that would, if not handled, cause your program to crash. Attempting to use exceptions in place of if statements is going to make your code very slow, very hard to read, and even harder to understand/maintain.
To take from your example: if you're adding to a hash table, and need to resize the table, why do you need to throw an exception, when you could just resize it? This is exactly how an std::vector works. If you do a push_back() on a vector and vector.capacity() < vector.size() + 1, the vector will internally re-allocate the buffer so that the new item can be added. The only time an exception might be thrown is if you run out of memory. The caller isn't aware of any of this, it just calls vector.push_back(...).

C++ try / catch (new to programming and not much info about this clause)

I am new to programming and am having trouble with try / catch clauses.
Here is an example from a textbook that I have:
int main( )
{
char *ptr;
try {
ptr = new char[ 1000000000 ];
}
catch( … ) {
cout << "Too many elements" << endl;
}
return 0;
}
I have tried to look online for a further explanation and the textbook does not exactly tell me what what these clauses actually do or what it is used for.
Any information would be helpful.
EDIT: The textbook I am using is:
C++: Classes and Data Structures by Jeffrey Childs
A try-catch is the C++ construct for exception handling. Google 'C++ exceptions'.
Try catch is a way of handling exceptions:
try
{
// Do work in here
// If any exceptions are generated then the code in here is stopped.
// and a jump is made to the catch block.
// to see if the exception can be handled.
// An exception is generated when somebody uses throw.
// Either you or one of the functions you call.
// In your case new can throw std::bad_alloc
// Which is derived from std::runtime_error which is derived from std::exception
}
// CATCH BLOCK HERE.
The catch block is where you define what exceptions you want to handle.
// CATCH BLOCK
catch(MyException const& e)
{
// Correct a MyException
}
catch(std::exception const& e)
{
// Correct a std::exception
// For example this would cat any exception derived from std::exception
}
You can have as many catch blocks as you like. If you exception matches any of the catch expressions in the catch statement then the associated block of code is executed. If no catch expressions matches an exception then the stack is unwound until it finds a higher level catch block and the processes is repeated (this can cause the application to exit if no matching catch block is found).
Note: If multiple catch expressions match then the lexically first one is used. Only one or none of the catch blocks will be executed. If none then the compiler will look for a higher level try/catch.
There is also a catch anything clause
catch(...)
{
// This is a catch all.
// If the exception is not listed above this will catch any exception.
}
So how does this apply to your code.
int main( )
{
char *ptr;
try
{
// This calls ::new() which can potentially throw std::bad_alloc
// If this happens then it will look for a catch block.
ptr = new char[ 1000000000 ];
// If the ::new() works then nothing happens and you pointer `ptr`
// is valid and code continues to execute.
}
catch( … )
{
// You only have one catch block that catches everything.
// So if there are any statements that generate an exception this will catch
// the excetption and execute this code.
cout << "Too many elements" << endl;
}
// As you have caught all exceptions the code will continue from here.
// Either after the try block finishes successfully or
// After an exception has been handled by the catch block.
return 0;
}
Try-catch blocks are used to trap errors in the code.
At the most basic level, errors occur because the program tries to execute an invalid instruction. That instruction (read: line of code) could be invalid for a number of reasons. In your specific instance, the instruction could be invalid if your program was not able to allocate 1,000,000,000 bytes of memory to story your ptr. The most common exception is trying to access a bad pointer, which is called a Null Pointer Exception, which occurs when you try to perform some action on an Object that either has not been created, or has been deleted (or got corrupt). You will learn to hate that exception.
Using catch(...) tells the program to execute the code inside the catch block if any error occurs inside the code within the try block. There you can handle your error and try to find someway to either fix the error condition or gracefully exit that module.
You can also catch specific errors, which you can find out more about here : http://www.cplusplus.com/doc/tutorial/exceptions/
If you already know C, try/catch achieves the same thing as setjmp/longjmp when used for error handling. Think of try as code for the if condition of setjmp and catch code for else of setjmp. This makes longjmp equivalent to throw in C++, which is used to throw an exception. In your example, probably, the new operator, which calls some memory allocation function internally, throws an exception on seeing a very large number as input by using the C++ throw operator.
void a()
{
.......
longjmp(buf,1); // <--- similar to throw
.......
}
if ( !setjmp(buf) ) // <--- similar to try
{
.......
a();
.......
}
else // <--- similar to catch
{
.......
}
try/catch is a bit more sophisticated than setjmp/longjmp, as for setjmp/longjmp you will need to declare variables which are modified in between setjmp/longjmp calls as volatile, which is not necessary for try/catch.

Using C dynamic memory functions in C++ to avoid Segmentation Fault

I'm trying to safely recover from a segmentation fault I expect to happen. I'm trying to avoid it checking using my canAlloc() function here. When canAllow returns false, A0 (which is Ackermann's if you didn't see it) should throw an exception that I can catch in the main method. checkTable and saveInTable are both functions that use a map<int hash, int value> to store returns from A0.
bool canAlloc(){
bool reBool = false;
int * memch = (int*)calloc (10000, sizeof(int));
reBool = (memch != NULL);
free(memch);
return reBool;
}
int A0(int m, int n){
if(!canAlloc()) throw;
int reInt = checkReturnTable(m,n);
if(reInt == -1){
if(m == 0){
return n + 1;
} else if(m > 0){
if(n == 0){
reInt = A0(m-1,1);
} else if(n > 0){
reInt = A0(m-1, A0(m,n-1));
}
}
saveInReturnTable(m,n,reInt);
return reInt;
} else return reInt;
}
From a comment:
In main I have a try-catch block to catch any exception try{} catch(...){}. As I understand it the three periods should catch any exception thrown. And as I understand, the throw keyword throws the exception without any specifiers, but can still be caught by the three dots.
A segmentation fault is not a C++ exception. It is indicative of a program failure that causes the OS to send a SIGSEGV signal to your process. You won't be able to catch a SIGSEGV signal directly; you'd have to set up a signal handler and ... well, it gets tricky at that point, because it is not clear that you can throw an exception from within a signal handler.
A throw with no exception specified rethrows the current exception; it only makes sense inside a catch block.
You probably get the SIGSEGV when your system is unable to extend the stack any further, probably because you've run out of virtual memory. That means one of your function calls failed because there was no space to put its arguments or local variables or return address, etc. There is no clean way to recover from that, which is why the system generates the segmentation fault.
If the fault was because calloc() could not allocate memory, you'd not get a segmentation fault; you'd get a zero return value. And you could raise an 'out of memory' exception cleanly and synchronously when it happens. But that isn't your problem.
You cannot recover from a segmentation fault, because once the fault occurs, your program is no longer in a well-defined state, and there's no mechanism to roll back to a well-defined state, either.
A segmentation fault is always a programming error in one way or another, and you must simply avoid it. In C++, you can simply catch exceptions coming from a dynamic allocation:
T * p;
try { p = new T; }
catch(const std::bad_alloc & e) { /* ... */ }
Usually there's no need to be quite that manual, though, since you would wrap your dynamic allocations inside suitable managing containers (like unique_ptr or shared_ptr), and you should catch exceptions (not even just allocation ones) at points in your program flow where you are in a position to handle the error and continue meaningfully.
(Thanks to exceptions you should not usually need to check the result of possibly throwing functions right at the call side - that's the whole point of using exceptions.)
If for some reason you just want to allocate raw memory, without constructing any object, you can do it in two ways:
// Method #1, the C++ way:
void * addr = ::operator new(n); // will throw std::bad_alloc on error
// Method #2, the manual way:
void * addr = std::malloc(n);
if (!addr) throw std::bad_alloc(); // throw exception manually, handled elsewhere

Is it okay to manually throw an std::bad_alloc?

I have this code..
CEngineLayer::CEngineLayer(void)
{
// Incoming creation of layers. Wrapping all of this in a try/catch block is
// not helpful if logging of errors will happen.
logger = new (std::nothrow) CLogger(this);
if(logger == 0)
{
std::bad_alloc exception;
throw exception;
}
videoLayer = new (std::nothrow) CVideoLayer(this);
if(videoLayer == 0)
{
logger->log("Unable to create the video layer!");
std::bad_alloc exception;
throw exception;
}
}
IEngineLayer* createEngineLayer(void)
{
// Using std::nothrow would be a bad idea here as catching things thrown
// from the constructor is needed.
try
{
CEngineLayer* newLayer = new CEngineLayer;
return (IEngineLayer*)newLayer;
}
catch(std::bad_alloc& exception)
{
// Couldn't allocate enough memory for the engine layer.
return 0;
}
}
I've omitted most of the non-related information, but I think the picture is clear here.
Is it okay to manually throw an std::bad_alloc instead of try/catching all of the layer creations individually and logging before rethrowing bad_allocs?
Just to answer the question (since nobody else seems to have answered it), the C++03 standard defines std::bad_alloc as follows:
namespace std {
class bad_alloc : public exception {
public:
bad_alloc() throw();
bad_alloc(const bad_alloc&) throw();
bad_alloc& operator=(const bad_alloc&) throw();
virtual ˜bad_alloc() throw();
virtual const char* what() const throw();
};
}
Since the standard defines a public constructor, you'd be perfectly safe to construct and throw one from your code. (Any object with a public copy constructor can be thrown, IIRC).
You don't need to do that. You can use the parameterless form of the throw statement to catch the std::bad_alloc exception, log it, then rethrow it:
logger = new CLogger(this);
try {
videoLayer = new CVideoLayer(this);
} catch (std::bad_alloc&) {
logger->log("Not enough memory to create the video layer.");
throw;
}
Or, if logger is not a smart pointer (which it should be):
logger = new CLogger(this);
try {
videoLayer = new CVideoLayer(this);
} catch (std::bad_alloc&) {
logger->log("Not enough memory to create the video layer.");
delete logger;
throw;
} catch (...) {
delete logger;
throw;
}
I personally DO throw it if I use some custom allocator in STL containers. The idea is to present the same interface- including in terms of behavior- to the STL libraries as the default std::allocator.
So, if you have a custom allocator (say, one allocating from a memory pool) and the underlying allocate fails, call "throw std::bad_alloc". That guarantees the caller, who 99.9999% of the time is some STL container, will field it properly. You have no control over what those STL implementations will do if the allocator returns a big fat 0- it is unlikely to be anything you'll like.
Another pattern is to use the fact that the logger is subject to RAII, too:
CEngineLayer::CEngineLayer( )
{
CLogger logger(this); // Could throw, but no harm if it does.
logger.SetIntent("Creating the video layer!");
videoLayer = new CVideoLayer(this);
logger.SetSucceeded(); // resets intent, so CLogger::~CLogger() is silent.
}
This scales cleanly if there are multiple steps. You just call .SetIntent repeatedly. Normally, you only write out the last intent string in CLogger::~CLogger() but for extra verbose logging you can write out all intents.
BTW, in your createEngineLayer you might want a catch(...). What if the logger throws a DiskFullException?