비지역 점프 - setjmp, longjmp로 흐름 전환하기
저희가 지금까지 알고 있던 흐름 제어 방식은 대부분 정상적인 함수 호출과 리턴이었는데요. 하지만 때로는 에러 발생 시 바로 밖으로 빠져나오거나, 예외 상황에서 원래의 안전 지점으로 되돌아가야 할 때가 있습니다. 이때 사용할 수 있는 강력한 저수준 도구가 바로 비지역 점프(Nonlocal Jump)입니다. C 언어에서는 이를 위해 두 가지 함수(setjmp, longjmp)를 제공합니다.
이번 글에서는 CSAPP 8.6절 내용을 바탕으로, 이 함수들이 어떻게 작동하며 언제 써야 하는지 정리해봅니다.
setjmp / longjmp의 기본 원리
setjmp()
#include <setjmp.h>
jmp_buf env;
int val = setjmp(env);
- 현재의 컨텍스트(레지스터, 스택 포인터 등)를 env에 저장
- 처음 호출 시에는 0을 반환
- 나중에
longjmp()
로 이 지점으로 복귀가 가능
longjmp()
longjmp(env, 42); // 이전 setjmp로 돌아감, 반환값은 42
- 이전에 setjmp로 저장해 둔 위치로 즉시 복귀
- 복귀하면
setjmp()
가 42를 반환 - 스택 프레임을 건너뛰고 튀어나오기 때문에, 흐름이 마치 점프하는 것처럼 작동
setjmp / longjmp의 작동 예시
#include <stdio.h>
#include <setjmp.h>
jmp_buf buf;
void foo() {
printf("in foo()\n");
longjmp(buf, 1); // setjmp 위치로 점프
}
int main() {
if (setjmp(buf) == 0) {
printf("setjmp returned 0\n");
foo();
} else {
printf("Back from longjmp!\n");
}
}
위 C 코드의 실행 흐름은 다음과 같습니다.
setjmp returned 0
in foo()
Back from longjmp!
만약 foo()
에서 에러가 발생하면 longjmp()
를 호출해 즉시 main으로 돌아가게 됩니다.
setjmp / longjmp 사용 시 주의사항
주의 포인트 | 설명 |
스택은 복원되지 않음 | 자동 변수(지역 변수)의 값은 보존되지 않을 수 있음 |
리턴값 0은 금지 | longjmp의 두 번째 인자에 0을 주면 setjmp가 0이 아닌 값을 반환해야 하므로, 내부적으로 1로 자동 변경됨 |
자원 정리 주의 | longjmp는 중간 함수들을 스킵하므로, 리소스 정리가 안 될 수 있음 |
따라서 longjmp는 빠르게 빠져나와야 할 에러 처리에 적합하고, 일반적인 흐름 제어에는 추천되지 않습니다.
setjmp / longjmp를 사용하는 경우
- 라이브러리 내부에서 치명적인 오류 발생 시 복구용
- 복잡한 중첩 함수 호출 중 특정 지점으로 흐름을 전환해야 할 때
- 예외 처리를 직접 구현해야 할 때 (C에는 try-catch가 없기 때문에)
핵심 요약
함수 | 역할 | 반환값 |
setjmp(env) | 현재 위치 저장 | 0 (처음 호출 시) or val (longjmp 시) |
longjmp(env, val) | 저장된 지점으로 점프 | setjmp가 val을 반환하게 됨 |
'크래프톤 정글 > 컴퓨터구조(CSAPP)' 카테고리의 다른 글
[CSAPP 9장 완전정복] 9.1~9.2 가상 메모리의 시작 - 주소와 주소 공간 이해하기 (0) | 2025.04.22 |
---|---|
[CSAPP 8장 완전 정복] 8.7~8.8 프로세스 도구 실전 사용 + 8장 전체 요약 (0) | 2025.04.21 |
[CSAPP 8장 완전 정복] 8.5 시그널, 비동기 흐름의 시작 (0) | 2025.04.21 |
[CSAPP 8장 완전 정복] 8.4 프로세스를 만들고 제어하는 기술들 - fork, exec, wait 완전 정복 (0) | 2025.04.19 |
[CSAPP 8장 완전 정복] 8.1~8.3 예외와 프로세스, 시스템의 흐름을 바꾸는 힘 (0) | 2025.04.19 |