13

I have such code as follows

try {
  doSomething();
} catch(InterruptException) {
  goto rewind_code;
}

if(0) {
rewind_code:
  longjmp(savepoint, 1);
}

My question is, is the exception object that is stored by the C++ runtime free'ed when I goto out of the catch block? Or is the runtime allowed to cache it until the surrounding function exists or something like that? I simply want to ensure that if I execute above code multiple times, each time taking the rewind code, I won't leak memory (because the longjmp won't execute cleanup code emitted by the compiler into or before function prologues).

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 9
    Who else could've asked this question? :) – Armen Tsirunyan Aug 31 '11 at 20:35
  • 1
    I know this is a theoretical exercise, but I can't resist posting the obligatory [xkcd](https://www.xkcd.com/292/) seeing the goto :-) – Praetorian Aug 31 '11 at 20:38
  • 2
    Any reasonable compiler should emit a `warning: what the heck are you doing?` when seeing this code. `:)` – Matteo Italia Aug 31 '11 at 20:45
  • I honestly hope this is a theoretical question... – Kornel Kisielewicz Aug 31 '11 at 20:58
  • 1
    @Korn errm. No it isn't. If you have a good idea on how to get rid of the `goto` that is equally simple, I'm all ears. Thanks for your generous insight! – Johannes Schaub - litb Aug 31 '11 at 21:01
  • Is there a compelling reason for not putting the try/catch block into a function and returning some code (say non zero) in the catch block ? You could then do `foo() && longjmp(savepoint, 1)` and forget about borderline and difficult to guarantee behavior. – Alexandre C. Aug 31 '11 at 21:24
  • 3
    Ummm, ouch. Mixing `throw/catch` and `longjmp` just seems to be asking for trouble. Big trouble. Trouble right here in River City kinds of trouble. `longjmp` is a C function; in a sense it is the C equivalent of `throw`. C has no requirements regarding how it treats C++, and C++ has no requirements on how `longjmp` performs. – David Hammen Aug 31 '11 at 21:50
  • @Johannes, if you would explain the reason for the code in the first place, maybe we could help? – Kornel Kisielewicz Sep 02 '11 at 12:06

2 Answers2

11

§6.6/2:

On exit from a scope (however accomplished), destructors (12.4) are called for all constructed objects with automatic storage duration...

At least as I'd read it, "however accomplished" should/does include a goto.

Edit: Okay, based on Johannes's comment, what we care about is §15.1/4:

When the last handler being executed for the exception exits by any means other than throw; the temporary object is destroyed and the implementation may deallocate the memory for the temporary object;

[ ... ]

The destruction occurs immediately after the destruction of the object declared in the exception-declaration in the handler.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Thanks. Though I'm not asking about the copy of the exception object. I see that the parameter of the catch clause will be destructed. But I'm asking about the original exception object that is kept behind the scenes and most probably allocated on the heap. I.e the one that would be rethrown by `throw;`. – Johannes Schaub - litb Aug 31 '11 at 20:44
  • Ah thanks. I suspect that means I can be reasonably sure that the memory is free'ed. – Johannes Schaub - litb Aug 31 '11 at 20:57
  • oh, that bit looks familiar. :D – Mooing Duck Aug 31 '11 at 20:58
  • @Johannes: Well, at least it means if it isn't freed, you have solid grounds for filing a bug report. This is a tricky enough area that I'm not sure being required by the standard *necessarily* translates into it actually happening (though the situation is certainly a lot better today than, say, 8 or 10 years ago). – Jerry Coffin Aug 31 '11 at 21:02
4

§ 15.1.4

The memory for the exception object is allocated in an unspecified way, except as noted in 3.7.4.1. If a handler exits by rethrowing, control is passed to another handler for the same exception. The exception object is destroyed after either the last remaining active handler for the exception exits by any means other than rethrowing, or the last object of type std::exception_ptr (18.8.5) that refers to the exception object is destroyed, whichever is later. In the former case, the destruction occurs when the handler exits, immediately after the destruction of the object declared in the exception-declaration in the handler, if any. In the latter case, the destruction occurs before the destructor of std::exception_ptr returns. The implementation may then deallocate the memory for the exception object; any such deallocation is done in an unspecified way.

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158