3. • 스레드가 생성되면 시스템은 프로세스의 주소 공간에 스레드 스택으로 사용할 영역을 예약
• 이 영역에 물리적 저장소를 일부 커밋
• 각각의 스레드는 자신만의 스택을 가진다
• 기본적으로 시스템은 1MB 의 주소 공간을 예약하고 이 중 물리적 저장소로 두 개의 페이지를 커밋
• 기본 설정은 마이크로소프트 C++ 컴파일러의 /F 옵션이나 마이크로소프트 링커의 /STACK 옵션으로 변경 가능
• CreateThread나 _ beginthreadex 함수 호출 할 때 커밋할 물리적 저장소의 크기 전달 가능
스레드 스택
Initflag 매개변수에 플래그를 지정하지 않으면
stack_size 는 커밋 크기를 지정
0으로 지정하면 시스템은 PE 헤더에
지정된 크기를 이용하여 물리적 저장소를 커멋
4. • 그림은 4KB 의 페이지를 사용하는 스택으로 예약된 영역 표현
• 스택 영역과 커밋된 물리적 저장소 모두 PAGE_READWRITE 보호 특성
• 예약 영역은 0x08000000으로부터 시작
• 예약된 영역 최상위 두 개의 페이지에 물리적 저장소를 커밋
• 스레드의 스택 포인터 레지스터는 예약된 영역의 최상위 페이지 끝을
(0x08100000)을 가리키도록 설정(스택을 사용할 때의 시작 위치)
스레드 스택 영역
5. • 스택 영역의 두 번째 페이지는 가드 페이지(guard page)
• 스레드가 함수를 계속 호출하면 호출 트리(call tree) 깊이 증가, 더 많
은 스택 공간 필요
• 스레드가 가드 페이지에 접근을 시도하게 되면,
• 시스템은 가드 페이지 이하에 추가적으로 페이지를 커밋,
• 현재 가드 페이지의 가드 페이지 보호 특성 해제
• 새롭게 커빗된 페이지에 대해 가드페이지 보호특성 설정
• 이를 통해 필요로 하는 크기에 맞게 스택의 물리적 저장소를 증가
• 스레드의 호출 트리가 계속해서 깊어지면 스택 영역은 [그림 16-2]와
같이 변경될 것이다.
가드 페이지
6. • 스레드의 호출 트리가 계속해서 깊어지면 스택 영역은 아래와 같이 변경
가드 페이지
7. • 0x8001000 페이지에 물리적 저장소 커밋할 때는 새로 커밋한 저장소에 대해 가드 보호 특성을 지정하지 않음
• 이것은 스택으로 예약된 주소 공간이 모두 물리적 저장소로 커밋되었다는 것을 의미
• 시스템은 0x08001000에 커밋할 때는 0xC00000FD로 정의되어 있는 EXCEPTION_STACK_OVERFLOW 예외 유발
• 구조적 예외 처리(SEH)를 이용하면 프로그램은 현재 상황에 대한 통지를 받을 수 있고, 예외 상황을 처리
스레드 스택 영역의 사용
8. • 스택 오버플로가 발생한 이후 스레드가 계속 스택을 사용하면 결국 0x08000000으로 시작하는 페이지도 접근
• 그럴 경우 시스템은 스레드가 심각한 에러 상황에 직면한 것으로 판단하고 접근 위반 예외를 유발
• 이러한 예외 상황이 발생하게 되면 시스템은 윈도우 에러 보고 서비스로 제어권을 전달하여 프로세스가 종료되기
전에 다음과 같은 다이얼로그 박스를 화면에 출력
• 시스템은 스택 영역의 최하위 페이지를 예약상태로 유지해서 스레드가 이 페이지에 접근하는 사실을 알 수 있다
• 이를 이용하여 프로세스가 사용하는 다른 데이터들이 실수로 덮어 쓰여지는 것을 막을 수 있다.
접근 위반 예외
9. • 함수가 배열에 대한 할당문을 수행하게 되면 스택의 끝을 초과
• 스택의 끝을 초과한 영역이 이미 다른 용도로 사용되는 경우라면 접근 위반 예외를 발생시키지 못함
스택 언더플로
10. • 오른쪽 코드는 스택 언더플로가 발생하는
경우 항상 데이터의 손실을 유발
스택 언더플로
11. • C/C++ 런타임 라이브러리에는 스택 확인 함수 존재
• 컴파일러는 스택 확인이 필요한 곳에 자동적으로 함수를 호출하도록 코드를 포함
• 스택 확인 함수는 스레드 스택으로 사용되는 영역에 물리적 저장소가 적절히 커밋되었는지 확인하는 역할
• 함수는 16,000 바이트의 공간을 정수형 배열로 사용
• 16 000바이트의 스택 공간을 할당은 단순히 CPU의 스택 포인터 값으로부터 16,000바이트를 빼는 작업
• 시스템은 이 영역에 대한 실질적인 접근이 이루어지기 전까지는 물리적 저장소를 커밋하지 않는다.
• 가드 페이지보다 더 아래에 있는 스택에 접근하면, 예약만 수행된 메모리에 대한 접근으로 접근 예외 발생
C/C++ 런타임 라이브러리의 스택 확인 함수
12. • 컴파일 과정에서 각 함수들의 스택의 크기를 결정
• 함수가 필요로 하는 스택의 크기가 개별 CPU의 페이지 보
다 더 큰 메모리를 필요로 하는 경우, 컴파일러는 자동적으
로 스택 확인 함수를 호출하는 코드를 삽입
• 오른쪽의 슈도코드는 스택 확인 함수의 작업 설명
C/C++ 런타임 라이브러리의 스택 확인 함수