Exceptions : interesting problems

Hi,

In order to test catching exceptions from an initialiser list, I deliberately did bad practice by hard coding an argument to a ctor that would cause a std::bad_allocto be thrown. Obviously better practice is to send a variable, but that would cause a compile error, so I hard coded a value.

The program I wrote creates Prime Numbers up to a specified limit which is an argument to the ctor of type std::size_t. The program works fine IMO, using g++ in cygwin:

$ time ./PrimesExe
Limit is 2000000
148933 Primes Created

real    0m1.210s
user    0m1.123s
sys     0m0.046s


Now when I send something invalid like a negative number or something too big for std::size_t, the program seems to run indefinitely, when compiled with g++ under cygwin. I haven't tested it yet on Linux.

However, if I do the same on VS2013 express, it takes about 15 seconds to print the expected caught exception message. I was not expecting it to take so ridiculously long compared to the reasonable amount of work involved in doing primes up to 2 million.

I have read up about what is involved in catching exceptions: stack unwinding, keeping track of what needs to be destroyed etc. But this is 1 object with 1 ctor argument, no Base classes or any other complications. So why such a long or indefinite amount of time?

This whole example is probably contrived, and I am wondering whether exceptions is the right tool for this - it is similar to the divide by zero problem, or could be considered a programming error to call a ctor with a bad argument?

Also, catching an exception thrown by an initaliser list seems a bit awkward in that one seems to have enclose the creation of the object and all subsequent uses of it (and any code in between ) in the same try block, otherwise it goes out scope. I suppose I could try to write a wrapper function that returns a smart pointer reference to a valid object, but I would have to test the validity of it's return too. That's the awkward part - there is probably a better way?

Are there any recommended ways of recovering from initialiser list exception, that is, to allow the user to enter a new hopefully valid value and try to create the object again?

Looking forward to any replies, thanks in advance :+)





> I have read up about what is involved in catching exceptions:

Now, read up on memory allocation, paging files and the like.
For instance: What would the OS need to do for a very large memory allocation if:
a. A variable page file size, starting at a low value, growable to a fairly high value was set
b. The logical volume on which the page file resides is heavily fragmented
c. That logical volume does not have a lot of free space
d. And a journalling file system like NTFS was being used


> Also, catching an exception thrown by an initaliser list seems a bit awkward in that
> one seems to have enclose the creation of the object and all subsequent uses of it
> (and any code in between ) in the same try block, otherwise it goes out scope.

That is true of any object with an automatic storage duration.
These objects are at block scope; the creation of the object and all subsequent uses of it would have to be within the same block.
There is nothing special if the block is a try-block.


> Are there any recommended ways of recovering from initialiser list exception,
> that is, to allow the user to enter a new hopefully valid value and try to create the object again?

You could put a function-try-block around the constructor.
http://en.cppreference.com/w/cpp/language/function-try-block
Hi,

Thanks for your reply :+)

For instance: What would the OS need to do for a very large memory allocation if:
a. A variable page file size, starting at a low value, growable to a fairly high value was set
b. The logical volume on which the page file resides is heavily fragmented
c. That logical volume does not have a lot of free space
d. And a journalling file system like NTFS was being used


I should have mentioned that the member variable is a std::list<std::size_t>, but the exception happens before that, in the initialiser list. I don't see any large memory allocation yet, that happens later when the list is added to. There is only 1 object created at the beginning of the program, and the exception should be thrown straight away, so I am having trouble imagining how much of anything has been allocated at this point in the execution.

As I mentioned in my OP, maybe the situation of a value being outside the accepted range for a particular type, means that using exceptions is the wrong approach, and the wrong value is considered a programming error? Maybe I should just test a run time value in the normal way?

I did it this way because I thought it would be an easy way to test a std::bad_alloc in the initialiser list.

There is nothing special if the block is a try-block.


Ok, but see below why this is a problem for me.

You could put a function-try-block around the constructor.


That is what I have already and is what I am testing.

The problem is when the exception is caught, is being able to go back to before the try block with new (hopefully valid) info, to have another go at creating the object. The try block might encompass all the code normally in main() , but the catch blocks are at the end, so this implies looping: do I just use goto ?

Hell, did I answer my own questions?

I still look forward to replies, Cheers

Topic archived. No new replies allowed.