setjmp()와 longjmp()함수를 사용하기 위해서는 먼저 setjmp.h를 포함해야한다.
#include <setjmp.h>
쉽게 생각하면 setjmp()는 시스템 복원 지점을 만들고, longjmp()는 시스템 복원을 하는 것과 같다.
setjmp()
int setjmp(jmp_buf env);
setjmp() 함수는 현재의 위치(스택 환경)을 저장하고, 나중에 longjmp() 함수를 호출되었을 때 그 위치로 다시 돌아가는 데 사용된다.
longjmp()
void longjmp(jmp_buf env, int val);
longjmp() 함수는 setjmp() 함수를 통해 저장된 위치로(스택환경으로) 프로그램 실행을 이동(복원)하는 데 사용된다.
longjmp() 함수가 호출되면 setjmp() 함수 호출 이후에 발생한 모든 지역 변수 및 레지스터 상태가 소멸됨을 의미한다.
jmp_buf
jmp_buf라는 자료형은 setjmp() 함수가 호출된 시점의 프로그램 상태를 저장하기 위한 버퍼로, jmp_buf에 저장되는 정보는 특정 구현과 컴파일러에 따라 다를 수 있지만, 일반적으로는 CPU 레지스터 정보와 함께 스택 프레임 정보가 포함된다.
이렇게 저장된 정보는 longjmp() 함수를 호출하여 setjmp() 함수가 호출되었던 위치로 돌아갈 때, 프로그램이 다시 해당 상태로 복원될 수 있도록 해준다.
따라서 jump_buf는 프로그램 실행 중에 메모리에 상주하며 어느 위치에서든 사용 가능한 전역변수나 static 변수로 선언될 필요가 있다.
setjmp() 함수의 리턴값
1. 최초 호출 : 스택 환경을 저장한 후 값 0을 리턴한다.
2. longjmp() 함수로 인한 복귀 : longjmp() 호출의 결과로 리턴하는 경우, longjmp() 함수를 통해 전달된 val 인수를 리턴한다.
따라서 setjmp()의 리턴값이 0인지 아닌지 확인하면, 최초호출인지 또는 longjmp()로 인한 복귀인지 알 수 있다.
주의사항
❗ longjmp() 함수 호출시 val 인수는 0이 아닌 값이어야 한다. 만약 val로 0을 전달하면 자동으로 이 값이 1로 대체된다. 최초호출을 구분하기 위해서이다.
❗ longjmp() 함수를 호출하기 전에 setjmp() 함수를 호출하는 함수가 리턴하지 않는지 확인해야 한다. setjmp() 함수를 호출하는 함수가 리턴된 후 longjmp()을 호출하면 예측 불가능한 작동이 발생할 수 있다.
- 만약 foo()에서 setjmp()를 호출했으면 foo()가 리턴한 후에 해당 env로(스택환경으로) longjmp()를 호출하면 오류가 발생한다는 뜻이다. main()에서 setjmp()를 호출하면 그런 걱정은 없겠다.
#include <stdio.h>
#include <setjmp.h>
jmp_buf env;
int main(void)
{
int ret;
char ch;
if ((ret = setjmp(env)) == 0) printf("line: %d, ret = %d\n", __LINE__, ret);
else printf("line: %d, ret = %d\n", __LINE__, ret);
while (1)
{
printf("Enter 'y' to jump to the beginning\n");
ch = getchar();
getchar();
if (ch == 'y')
{
longjmp(env, ++ret);
}
}
return 0;
}
참고자료 : https://www.ibm.com/docs/ko/i/7.3?topic=functions-longjmp-restore-stack-environment
'프로그래밍 > C' 카테고리의 다른 글
C ] 포인터와 const (0) | 2023.05.30 |
---|---|
C ] 비트필드와 공용체 사용 (0) | 2023.05.29 |
C언어 ] 맵 자료구조 구현 (0) | 2023.05.07 |
C ] float to hex / hex to float Converter (0) | 2023.04.09 |
C ] 시간복잡도가 O(1)인 2의 거듭제곱 판별 (0) | 2023.03.31 |