9

What happens when an unhandled exception is thrown from a constructor? For Java, and for C++? Will there be a memory leak?

dacongy
  • 2,504
  • 3
  • 30
  • 48
  • For Java, won't the program just crash? Your IDE probably won't even let you compile it. – Michael Dec 21 '12 at 01:16
  • I don't think you'd have to worry about that in Java, and if there is a situation where this could occur in C++, then use an std::auto_ptr. – Name Dec 21 '12 at 01:16
  • What do you mean by "unhandled exception is thrown"? How can you throw a handled exception? – Kerrek SB Dec 21 '12 at 01:36
  • @KerrekSB: Fairly sure this means "exception is thrown and not handled". – Dietrich Epp Dec 21 '12 at 02:10
  • Regarding Java you may read Jon Skeet answer in other SO question: http://stackoverflow.com/a/1371559/660990 – lpinto.eu Dec 21 '12 at 01:24
  • 1
    It's important to realize that in C++, members are usually destroyed when a constructor throws. Of course, after an uncaught exception the program ends, which makes the question fairly academic. – MSalters Dec 21 '12 at 16:44

8 Answers8

7

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 function std::terminate() is called; whether or not the stack is unwound before this call to std::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 no catch clause that can handle an exception can be found, then the current thread (the thread that encountered the exception) is terminated. Before termination, all finally 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.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • 1
    @anonymous downvoter: please explain your downvote so that others can learn from your insight(s). – Cheers and hth. - Alf Dec 21 '12 at 08:46
  • @Cheers-and-hth-alf The downvote was for the original version of your post which was very short and could have been summarized as "I dunno, I dunno, I dunno"; not a quality answer in my perspective (looked like a quick post to put a foot in the door before coming up with an actual answer to the question: a practice that is plaguing this forum). With the edits and standard quotes, it passes the bar for me. Downvote reverted, it served its purpose. – Mikael Persson Dec 21 '12 at 18:39
  • @MikaelPersson: thanks for explaining that vote. originally i wrote that i didn't know whether Java `final` blocks were processed. after that i added the standard and spec quotes, where that issue was resolved. so it seems that at least in your case that explicit statement colored the perception to the degree that you thought the *same* content as now was "dunno dunno dunno". i think that means that here on SO, instead of steering perception of technical issues away from premature conclusions, i need to prioritize not steering perception of the content in the direction of worthless. :-) – Cheers and hth. - Alf Dec 21 '12 at 19:18
  • 1
    Calling std::terminate is not exactly the same as terminating a program. – Arthur P. Golubev Aug 26 '21 at 23:41
6

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)

Thilo
  • 257,207
  • 101
  • 511
  • 656
2

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.

cmc
  • 2,061
  • 1
  • 19
  • 18
  • in c++ it is not guaranteed that the exception would "go on and on", in the sense of exception propagation. but it is unclear whether you're talking about propagation or the search for a handler. i don't think it's right to downvote for being unclear, so i'm just leaving this comment so that you can fix your answer. – Cheers and hth. - Alf Dec 21 '12 at 02:27
1

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?

Community
  • 1
  • 1
Lawrence Ward
  • 549
  • 1
  • 5
  • 17
0

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

paulsm4
  • 114,292
  • 17
  • 138
  • 190
  • Most of all exceptions must be unchecked! – lpinto.eu Dec 21 '12 at 01:25
  • From the [Java documentation](http://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html): "Here's the bottom line guideline: If a client can reasonably be expected to recover from an exception, make it a checked exception. If a client cannot do anything to recover from the exception, make it an unchecked exception." – paulsm4 Dec 21 '12 at 04:32
0

For C++, the answer is in the C++ FAQ.

How can I handle a constructor that fails?

How should I handle resources if my constructors may throw exceptions?

More info from GOTW

user93353
  • 13,733
  • 8
  • 60
  • 122
  • The FAQ does not, as I recall, go into the issues of unhandled exceptions. However, it may be that the OP meant to ask "what happens if a constructor throws an exception", not "what happens if a constructor throws an unhandled exception". if so, if the OP meant to ask something very different from what was asked, then your answer might be valuable. – Cheers and hth. - Alf Dec 21 '12 at 02:08
-1

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"].

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • -1 at least for c++ two phase construction is not an answer, it is a problem. and it is a very well known problem, we're into basics here. there is some discussion (not complete though) of it in the appendix about exception safety in the standard library in the 3rd edition of bjarne stroustrup's "the c++ programming language", and that appendix is available in PDF format from Bjarne's site. – Cheers and hth. - Alf Dec 21 '12 at 01:57
  • So, it's better to throw exceptions in the constructor? Surely both solutions are bad, but if you MUST throw exceptions, don't do it in the constructor. – Mats Petersson Dec 21 '12 at 01:58
  • 2
    throwing from a constructor ensures there is no incomplete object around. the c++ creation machinery supports this, and it's how all quality code handles construction failure (including the standard library). it is however irrelevant to the question at hand, for c++, since the "in a constructor" is irrelevant. :-) – Cheers and hth. - Alf Dec 21 '12 at 02:01
  • 2
    (In C++) two phase construction is a terrible idea -- almost the entire language and standard library is designed around the idea of acquiring resources in constructors and releasing resources in destructors. Two-phase construction implies the existence of an "constructed but unusable" value for objects, this increases the amount of state that must be considered, and reduces type-safety. It is much better to just stick to the guideline "manage resources using explicit resource-management classes which only manage a single resource". – Mankarse Dec 21 '12 at 02:16
-1

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. The finally blocks are guaranteed to be executed during the unwinding, but, of course, they must contain code to release the resource allocated in the corresponding try 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).

Mikael Persson
  • 18,174
  • 6
  • 36
  • 52
  • 1
    -1 "In C++ or Java, it might never find one and thus unwind all the way back to the start and terminate the program" is incorrect for C++. C++ does not guarantee stack unwinding for an unhandled exception. – Cheers and hth. - Alf Dec 21 '12 at 08:49
  • 1
    Indeed, which is why you should have a function try block on main, catching everything. This will guarantee stack unwinding even on systems that would otherwise not have it. – MSalters Dec 21 '12 at 16:48