Namespaces
Variants

longjmp

С ru.cppreference.net
Определено в заголовке <setjmp.h>
void longjmp( jmp_buf env, int status );
(until C11)
_Noreturn void longjmp( jmp_buf env, int status );
(since C11)
(until C23)
[[noreturn]] void longjmp( jmp_buf env, int status );
(since C23)

Загружает контекст выполнения env сохранённый предыдущим вызовом setjmp. Эта функция не возвращается. Управление передаётся в место вызова макроса setjmp который установил env. Этот setjmp затем возвращает значение, переданное как status.

Если функция, вызвавшая setjmp завершилась (возвратом или другим longjmp выше по стеку), поведение не определено. Иными словами, разрешены только длинные переходы вверх по стеку вызовов.

Переходы между потоками (если функция, вызвавшая setjmp была выполнена другим потоком) также являются неопределённым поведением.

(since C11)

Если когда setjmp был вызван, переменная VLA или другого изменяемо-модифицируемого типа находилась в области видимости и управление покинуло эту область, longjmp к тому setjmp вызывает неопределённое поведение, даже если управление осталось внутри функции.

При подъёме по стеку, longjmp не освобождает никакие VLA, могут возникнуть утечки памяти, если время их жизни завершается таким образом:

void g(int n)
{
    int a[n]; // a may remain allocated
    h(n); // does not return
}
void h(int n)
{
    int b[n]; // b may remain allocated
    longjmp(buf, 2); // might cause a memory leak for h's b and g's a
}
(since C99)

Параметры

env - переменная, ссылающаяся на состояние выполнения программы, сохранённое вызовом setjmp
status - значение, которое должно быть возвращено из setjmp. Если оно равно 0, 1 используется вместо него

Примечания

longjmp предназначена для обработки неожиданных ошибочных ситуаций, когда функция не может вернуться осмысленно. Это похоже на обработку исключений в других языках программирования.

Пример

#include <setjmp.h>
#include <stdio.h>
#include <stdnoreturn.h>

jmp_buf my_jump_buffer;

noreturn void foo(int status)
{
    printf("foo(%d) called\n", status);
    longjmp(my_jump_buffer, status + 1); // will return status+1 out of setjmp
}

int main(void)
{
    volatile int count = 0; // modified local vars in setjmp scope must be volatile
    if (setjmp(my_jump_buffer) != 5) // compare against constant in an if
        foo(++count);
}

Вывод:

foo(1) called
foo(2) called
foo(3) called
foo(4) called

Ссылки

  • Стандарт C23 (ISO/IEC 9899:2024):
  • 7.13.2.1 Макрос longjmp (стр. 283-284)
  • Стандарт C17 (ISO/IEC 9899:2018):
  • 7.13.2.1 Макрос longjmp (стр. 191-192)
  • Стандарт C11 (ISO/IEC 9899:2011):
  • 7.13.2.1 Макрос longjmp (стр. 263-264)
  • Стандарт C99 (ISO/IEC 9899:1999):
  • 7.13.2.1 Макрос longjmp (стр. 244-245)
  • Стандарт C89/C90 (ISO/IEC 9899:1990):
  • 4.6.2.1 Функция longjmp

См. также

сохраняет контекст
(макрос-функция)