[컴퓨터구조] 스택 프레임(stack frame)
스택 프레임
스택 프레임(stack frame)은 함수 호출 시 생성되는 작은 메모리 블록으로 지역 변수와 매개변수가 저장되는 영역이다.
스택 영역은 함수의 호출과 함께 할당되며, 함수의 호출이 완료되면 소멸합니다.
함수가 호출되면 스택에 매개변수, 호출이 끝난 뒤 돌아갈 반환 주소, 함수에서 선언된 지역 변수 등이 저장된다.
이렇게 스택 영역에 차례대로 저장되는 함수의 호출 정보를 스택 프레임(stack frame)이라고 합니다.
이러한 스택 프레임 덕분에 함수의 호출이 모두 끝난 뒤에, 해당 함수가 호출되기 이전 상태로 되돌아갈 수 있습니다.
스택 프레임 정보
명칭 | 설명 |
지역 변수 (Local Variables) | 함수 내 선언된 지역 변수는 함수 실행 동안 유효하고 함수 종료시 스택 프레임과 함께 제거 |
매개변수 (Parameters) | 함수 호출 시 전달된 매개변수 값은 스택 프레임에 저장되고 함수 내부에서 이 매개변수 값을 사용한다. |
반환 주소 (Return Address) | 함수 호출 전 어느 위치에서 호출되었는지 나타내는 주소. 함수 실행 완료시 주소를 사용하여 호출한 위치로 복귀 |
이전 스택 프레임 포인터 (Previous Stack Frame Pointer) |
호출된 함수의 이전 스택 프레임을 가르키는 포인터. 함수 호출 시 새로운 스택 프레임이 이전 스택 프레임을 가리키는 방식으로 생성되고 이를 통해 호출 스택의 연결 구조를 형성한다. |
스택 프레임의 동작
스택 프레임은 함수 호출이 중첩되면 스택에 여러 개가 순차적으로 쌓이는 구조이다.
즉, 가장 나중에 저장된 데이터가 가장 먼저 인출되는 후입선출(LIFO, Last-In First-Out) 방식으로 동작한다.
이때 스택은 푸시(push) 동작으로 데이터를 저장하고, 팝(pop) 동작으로 데이터를 인출한다.
함수가 호출될 때마다 새로운 스택 프레임이 생성되며, 함수 실행이 완료되면 해당 스택 프레임이 제거되면서 호출한 함수로 복귀한다.
이러한 방식으로 스택 프레임은 함수 호출과 복귀의 관리를 도와준다.
int main(void)
{
func1(); // func1() 호출
return 0;
}
void func1()
{
func2(); // func2() 호출
}
void func2()
{
}
Step 1. 프로그램이 실행되면, 가장 먼저 main() 함수가 호출되어 main() 함수의 스택 프레임이 스택에 저장
Step 2. func1() 함수를 호출하면 해당 함수의 매개변수, 반환 주소값, 지역 변수 등의 스택 프레임이 스택에 저장
Step 3. func2() 함수를 호출하면 해당 함수의 스택 프레임이 추가로 스택에 저장
Step 4. func2() 함수의 모든 작업이 완료되어 반환되면, func2() 함수의 스택 프레임만이 스택에서 제거
Step 5. func1() 함수의 호출이 종료되면, func1() 함수의 스택 프레임이 스택에서 제거
Step 6. main() 함수의 모든 작업이 완료되면, main() 함수의 스택 프레임이 스택에서 제거되면서 프로그램이 종료
스택 오버플로우 (stack overflow)
스택 오버플로우는 제공된 메모리 한도를 넘어 스택 프레임을 쌓을 경우 발생한다.
이렇게 스택의 모든 공간을 다 차지하고 여유 공간이 없는 상태에서 또 스택 프레임을 저장하게 되면 발생하는 것이다.
단, 이렇게 해당 스택 영역을 넘어가도 데이터가 저장될 수 있으면, 해당 프로그램은 오동작을 하게 되거나 보안상의 크나큰 취약점을 가지게 된다.
따라서 C언어에서는 실행 중인 프로그램에서 스택 오버플로우가 발생하면, 에러를 발생하고 곧바로 강제 종료시킨다.