Search code examples
c++exceptionsetjmp

C++: will an std::runtime_error object leak in a longjmp?


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?


Solution

  • 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.