C++

[C++] 스택 풀기(Stack Unwinding)

yeoul0714 2025. 4. 19. 02:10

스택 풀기란?

스택 풀기는 예외가 발생한 후, 적절한 catch 블록을 찾아 제어를 이동시키는 과정입니다.

 

이 과정에서 예외 발생 지점부터 catch 블록까지의 스택 프레임들을 풀어내는 작업이 이루어집니다.

스택 풀기 과정

  1. 예외 발생: 코드에서 throw 문이 실행되어 예외 객체가 생성됩니다.

  2. 적절한 핸들러 검색: 현재 함수 내에서 적절한 catch 블록을 찾습니다.
    없다면 호출 스택을 거슬러 올라가며 계속 검색합니다.

  3. 스택 프레임 정리: 예외 발생 지점과 catch 블록 사이의 모든 스택 프레임을 풀어냅니다. 이 과정에서:
    • 해당 범위의 모든 지역 객체들의 소멸자가 호출됩니다.
    • 소멸자는 생성된 순서의 역순으로 호출됩니다.
  4. 예외 처리: 적절한 catch 블록이 발견되면, 예외 객체가 해당 핸들러로 전달되고 처리됩니다.

  5. 정상 흐름 복원: 예외 처리 후, 프로그램은 catch 블록 이후 코드부터 정상 실행을 계속합니다.

이렇게 글로만 보면 이해가 힘드니 예시를 통해서 이해를 해보도록 합시다.

#include <iostream>
#include <stdexcept>

class Resource {
public:
    Resource(const std::string& name) : name_(name) {
        std::cout << "Resource " << name_ << " 생성됨" << std::endl;
    }
    
    ~Resource() {
        std::cout << "Resource " << name_ << " 소멸됨" << std::endl;
    }
    
private:
    std::string name_;
};

void level3() {
    Resource r3("Level 3");  // r3 생성
    std::cout << "level3 함수 실행 중..." << std::endl;
    throw std::runtime_error("level3에서 예외 발생!");  // 예외 발생
    // 이 아래 코드는 실행되지 않음
}

void level2() {
    Resource r2("Level 2");  // r2 생성
    std::cout << "level2 함수 실행 중..." << std::endl;
    level3();  // level3 호출
    // 이 아래 코드는 실행되지 않음
}

void level1() {
    try {
        Resource r1("Level 1");  // r1 생성
        std::cout << "level1 함수 실행 중..." << std::endl;
        level2();  // level2 호출
        // 이 아래 코드는 실행되지 않음
    }
    catch (const std::exception& e) {
        std::cout << "예외 잡힘: " << e.what() << std::endl;
    }
    
    std::cout << "level1 함수 정상 종료" << std::endl;
}

int main() {
    std::cout << "프로그램 시작" << std::endl;
    
    // main 함수에서도 Resource 객체를 생성해봅시다
    Resource rMain("Main");
    
    level1();  // level1 호출
    
    std::cout << "프로그램 종료" << std::endl;
    
    // 여기서 rMain의 소멸자가 호출됩니다 (main 함수 종료 시)
    return 0;
}

 

실행결과

프로그램 시작
Resource Main 생성됨
Resource Level 1 생성됨
level1 함수 실행 중...
Resource Level 2 생성됨
level2 함수 실행 중...
Resource Level 3 생성됨
level3 함수 실행 중...
Resource Level 3 소멸됨
Resource Level 2 소멸됨
Resource Level 1 소멸됨
예외 잡힘: level3에서 예외 발생!
level1 함수 정상 종료
프로그램 종료
Resource Main 소멸됨

 

자 흐름을 보면 level1()에서 level3()까지 호출되고

 

level3()함수에서 예외가 발생하게 됩니다.

 

그렇게 되면 level3() 블럭안에서는 함수를 처리해줄 부분이 없기 때문에

 

스텍프레임을 따라서 위로 하나씩 올라가게 됩니다.

 

그러면서 해당 블럭을 벗어나게 되면 소멸자도 함께 호출하게 됩니다.

 

그렇게 level1()블럭까지 오게되어 try블럭을 벗어나는 순간에 level1의 객체도 소멸하게 됩니다.

 

그리고 catch에서 예외가 잡히게 되고

 

그 이후의 코드가 차례대로 실행되게 됩니다.

 

이러한 메커니즘으로 C++은 예외를 처리하게 됩니다.