Suppose I have some C++ code which has a try-catch block in which the catch
part will trigger a long jump:
#include <stdexcept>
#include <stdio.h>
#include <setjmp.h>
void my_fun()
{
jmp_buf jump_buffer;
if (setjmp(jump_buffer))
return;
try {
std::string message;
message.resize(100);
snprintf(&message[0], 100, "error code %d\n", 3);
throw std::runtime_error(message);
}
catch (std::runtime_error &e) {
longjmp(jump_buffer, 1);
}
}
Since the std::runtime_error
object was allocated dynamically somewhere, will it leak the memory that was allocated for it or for the string?
This is kind of complicated. About longjmp
's validity, the standard says:
A setjmp/longjmp call pair has undefined behavior if replacing the setjmp and longjmp by catch and throw would invoke any non-trivial destructors for any objects with automatic storage duration.
runtime_error
has a non-trivial destructor, so the question is whether the exception object has "automatic storage duration". It does not. This suggests that longjmp
should be fine.
In addition, exception object destruction can happen in one of two places:
The points of potential destruction for the exception object are:
when an active handler for the exception exits by any means other than rethrowing, immediately after the destruction of the object (if any) declared in the exception-declaration in the handler;
when an object of type std::exception_ptr that refers to the exception object is destroyed, before the destructor of std::exception_ptr returns.
longjmp
is not "rethrowing". So in theory, this should be fine thanks to bullet point 1.
That being said, never rely on this. I highly doubt that implementations of longjmp
handle this correctly, and even if some do, it's probably not something you can expect.