C++ Exceptions
Posted: November 8th, 2019, 9:41 pm
Perhaps you've heard of them, they are a way of halting a program dead in it's tracks if an irrecoverable error occurs. Say you have a program that depends on a specific file being loaded, but the file is lost or corrupted. There isn't a point in returning an error code since there's nothing you can do but tell the user about such a problem and they must reinstall the program. This is a perfect scenario for throwing an exception.
There are some warnings about exceptions though. One is pretty widely talked about or at least it's something I've heard many people bring up on C++ and exceptions is never let your destructors throw an exception. The reason for this is because when an exception is thrown, the program begins to unwind it's stack. This starts calling destructors for any variables declared locally all the way back to either the beginning of the program or the first catch block it comes across. If during that period of unwinding and calling destructors another exception is thrown the program is required to call terminate(). When this happens, the program quits without calling any more destructors and resources may or may not be released back to the operating system upon program exit.
Now, here's another interesting thing I just ran across. If a constructor throws, it's destructor is NOT called. This makes sense because it means the object is not fully formed so destruction may be meaningless. What happens though to open files or memory that's already been allocated? Well, quite frankly, they are dropped on the floor, gone forever, or until next reboot or maybe the OS will do the cleanup when program ends I'm not sure. I'll have to do some digging I suppose.
That being the case, things become difficult in determining how to handle constructing objects in my opinion. In the case above where your program relies on a file being there and not corrupt, you may want to start putting try/catch blocks around these types and if an exception is thrown, release any other resources that may have been acquired before the attempt at loading the failed resource.
I'll try coming up with examples and get back on some suggestions for handling such behavior. Just something to think about. Unfortunately, this makes delayed initialization more appealing.
There are some warnings about exceptions though. One is pretty widely talked about or at least it's something I've heard many people bring up on C++ and exceptions is never let your destructors throw an exception. The reason for this is because when an exception is thrown, the program begins to unwind it's stack. This starts calling destructors for any variables declared locally all the way back to either the beginning of the program or the first catch block it comes across. If during that period of unwinding and calling destructors another exception is thrown the program is required to call terminate(). When this happens, the program quits without calling any more destructors and resources may or may not be released back to the operating system upon program exit.
Now, here's another interesting thing I just ran across. If a constructor throws, it's destructor is NOT called. This makes sense because it means the object is not fully formed so destruction may be meaningless. What happens though to open files or memory that's already been allocated? Well, quite frankly, they are dropped on the floor, gone forever, or until next reboot or maybe the OS will do the cleanup when program ends I'm not sure. I'll have to do some digging I suppose.
That being the case, things become difficult in determining how to handle constructing objects in my opinion. In the case above where your program relies on a file being there and not corrupt, you may want to start putting try/catch blocks around these types and if an exception is thrown, release any other resources that may have been acquired before the attempt at loading the failed resource.
I'll try coming up with examples and get back on some suggestions for handling such behavior. Just something to think about. Unfortunately, this makes delayed initialization more appealing.