what happens when an unhandled exception is thrown from a constructor-Collection of common programming errors
-
For Java: Control flow returns to the caller just like with an exception being thrown from a regular method. No memory leak (the half-constructed instance will be discarded and garbage-collected)
-
You ask,
“What happens when an unhandled exception is thrown from a constructor? For Java, and for C++? Will there be a memory leak?”
An unhandled exception is an exception that does not have an associated handler.
In C++ any unhandled exception terminates the program. It is unspecified whether the stack is unwound in this case, i.e. destructors of successfully constructed local variables may be executed or not depending on the compiler. Where the exception is throw from (such as inside a constructor) is irrelevant.
C++11 §15.3/9:
“If no matching handler is found, the functionstd::terminate()
is called; whether or not the stack is unwound before this call tostd::terminate()
is implementation-defined.”An unhandled exception in Java likewise necessarily terminates the program, or at least the current thread if it’s not the main thread, but with guaranteed calls of
finally
clauses:Java SE 7 Language Specification §11.3:
“If nocatch
clause that can handle an exception can be found, then the current thread (the thread that encountered the exception) is terminated. Before termination, allfinally
clauses are executed […]”Since the program terminates there is in practice no memory leak for the program itself, because in practice the operating system cleans up after a process.
However, a crashing program may leave temporary files on disk, and it may leak other resources from server processes, including memory leaks in those server processes.
-
Well, in C++ at least, an unhandled exception would just go on and on until it reaches your main() and thus closes your program. Not freed memory would then be taken care of by the operating system.
Not sure if that answers your question…?
So, basically, it’s just like if it was thrown from any other function.
-
You could have a memory leak if you create dependent objects inside the constructor.
In any language/environment this could cause a leak if these dependents are referenced by external entities which don’t clean them up.
In JAVA and C# this WILL NOT cause a leak if the dependents are not referenced externally. The garbage collector will eventually clean then up.
In C++ this WILL CERTAINLY cause a leak if the dependents are not referenced externally.
see Jon’ answer for more possibilities: Can constructors throw exceptions in Java?
-
It’s worth adding:
1) Java distinguishes between “checked” and “unchecked” exceptions
2) Most user-defined exceptions should be “checked”. This means the code won’t even compile unless each module in the call chain either a) handles the exception, or b) explicitly marks that it can “throw” the exception
-
Whether you get a memory leak or not depends on how the code is written. If you write “good” code, you shouldn’t have a memory leak. But it’s entirely possible to come up with scenarios where this goes horribly wrong.
If the constructor allocates anything in the constructor, then things may well go wrong.
The solution, in general is to use what’s called “two-phase construction”, so the constructor itself is very simple and “can’t go wrong”. Once the object is constructed, you call a member function that fills in the object in ways that could perhaps fail, and you can then throw exceptions at will, and as long as it’s ensured that the destructor is run at some point down the line, all should work out well. Beware of “part-constructed object in destructor” tho’ – what happens if your pointers are NULL, or if something else hasn’t been constructed partway through the destructor.
[The above is subject to “there is a handler somewhere before we get back to main, and we do actually want to do something other than abort the entire program”].
-
The situation is similar yet different in both languages, C++ or Java.
When the exception is thrown, it propagates back up the stack, looking for a handler. In C++ or Java, it might never find one and thus unwind all the way back to the start and terminate the program. In Java, there is a concept of checked exceptions which enforce that there will be some kind of handling of the exception (if checked). In C++, there is a concept of exception specification, but it is impractical (ill-designed) and should not be used, so, consider all exceptions as “unchecked” in C++.
Whether the exception ends up terminating the program or being caught somewhere far up-stream of where it was thrown, the unwinding process leading up to that is what matters. If it ends up terminating the program, then, of course, there are no memory leaks as the OS reclaims the memory. What you have to worry about is:
- Memory leaks during unwinding if the exception is eventually handled somewhere upstream; and,
- Other kinds of resources that could leak (e.g., pending database operations, network connections, etc.) because they won’t be reclaimed / undone by the OS if the program terminates.
As the stack unwinding occurs, in C++, the guarantee is, simply put, that every stack-bound object that was fully constructed (including the data members or base class instance of an object being constructed) will be destroyed immediately (i.e., deterministically) in the exact reverse order in which they were created. So, as long as all resources are tied directly to the construction / destruction of objects (also called “RAII”) there will be no leaks (of memory or other resource) during the unwinding process since every resource successfully acquired will be freed (unless freeing the resource fails during unwinding, which is something you need to handle with care).
In Java, the “stack” unwinding occurs in the same fashion, except that instead of immediately destroying the objects, they are marked as discarded (i.e., to be garbage collected), and eventually destroyed at some indeterminate point in the future. This guarantees no memory leaks, as long as the garbage collector stays alive long enough to do its job, which I’m not sure is guaranteed if the program ends up terminating on an unhandled exception (but it doesn’t matter at that point). The main problem in Java are the other resources. These resources must be released in the
finally
blocks. Thefinally
blocks are guaranteed to be executed during the unwinding, but, of course, they must contain code to release the resource allocated in the correspondingtry
block. As long as the programmer did his job, resources won’t leak.The fact that the exception is thrown from a constructor really doesn’t make much of a difference, and the basic rules are just the same basic rules for not leaking resources when exceptions are thrown:
- In C++, tie every single resource (memory or otherwise) to a single object, and the language guarantees the rest, no leaks. This is the Resource Acquisition Is Initialization (RAII) idiom.
- In Java, make sure the write every single non-memory resource acquisition within its own try-block which has its own finally-block that releases that single resource.
In both cases, you must release your resources cleanly (no-throw).
Originally posted 2013-11-27 12:10:28.