0. 함수 호출 규약이란

  • 어떤 함수를 호출할 때 함수의 인자를 어떤 방식으로 넘겨주는가에 대한 약속

 

1. 스택 프레임

  • 함수가 호출될 때마다 높은 주소에서 낮은 주소로 스택이 쌓이는 형태로 함수의 정보를 담고 있음
  • 함수의 정보란 매개 변수, 반환값, 지역변수를 의미함
  • 메모리의 스택 영역에 저장되는 정보임
  • 위 사진과 같이 함수가 불릴 때 마다 함수의 정보들이 쌓이는 것을 스택 프레임이라고 함
  • 스택의 자료구조 특성 상 맨 나중에 불린 함수가 먼저 정리되고 함수가 불리고 끝나고를 반복하며 이 스택프레임이 쌓였다가 정리되었다가 하는 과정이 프로그램 실행 중에 계속 일어나고 있는 것이다.

 

2. 메모리 오버플로우

  • 사용하고자 하는 메모리 공간보다 더 사용하여 다른 메모리 공간이 덮어씌워지는 경우를 일컫음
  • 주로 버퍼 오버플로우라 하는 것 같고 해킹 용어로 보임
int* pa = new int[10];
pa[11] = 20;  //buffer overflow!!
  • 위 코드가 간단한 예시가 될 수 있을 것 같다.

 

3. EBP, ESP 레지스터

  • 레지스터란 CPU가 요청을 처리하는데 필요한 데이터를 일시적으로 저장해주는 기억 장치
  • EBP, ESP는 스택 프레임에서 최상단 함수의 시작과 끝 주소라고 생각하면 됨
  • 위 사진의 Step3에서 Func1()의 초록과 주황 사이를 EBP가 가리키고 Func2()의 초록색 부분의 최상단을 ESP가 가리킨다고 보면 된다.
  • 이 때 함수가 불려있는 중엔 EBP는 변할 일이 없고 ESP는 PUSH, POP이라는 어셈블리어에 의해 위치가 계속 변하게 된다.
  • 함수가 정리되게 되면 ESP는 기존 EBP의 위치를 물려받을 것이고 EBP는 이전 함수의 스택 프레임의 주소를 알게 될 것이다.

 

4. 함수 호출 규약

  • cdecl, stdcall, fastcall, thiscall 등이 있음, 중요한 특징만 나열하고자 함
  • cdecl : Caller가 StackFrame 정리 -> 가변 인자 가능, main 함수, C, C++의 함수에 따로 지정하지 않는다면 이 호출 규약을 따름
  • stdcall : Callee가 StackFrame 정리 -> 가변 인자 불가능, WinAPI 프로그래밍에서 WINAPIENTRY라는 치환 구문이 __stdcall임(WinMain)
  • fastcall : stdcall과 크게 다르지 않으나 인자에서 2개까지 레지스터로 전달해주어 더 빠른 처리가 가능하다고 함
  • thiscall : 클래스의 멤버함수는 이 호출 규약을 따르며 클래스 내 this 포인터의 사용이 가능한 것이 이 호출규약 덕분. 기본적으론 가변인자가 불가능하다고 함.

 

5. 가변 파라미터 함수 구현

  • #include <cstdarg>
  • va_list, va_start, va_arg, va_end
  • 가변인자의 주소를 알기 위한 va_list 변수 -> va_list arg_pointer;
  • va_list 변수의 주소를 찾아주는 va_start -> va_start(arg_pointer, 고정인자의 마지막 변수);
  • 실제 가변인자들을 불러오는 va_arg -> int num = va_arg(arg_pointer, int);
  • int 크기만큼 포인터 주소를 옮겨가며 값을 읽는 것
  • va_list 변수를 nullptr로 비워주는 va_end -> va_end(arg_pointer);

'C++ > 키워드 정리' 카테고리의 다른 글

키워드 정리 [8] - 정수, 실수  (1) 2023.12.01
키워드 정리 [7] - 컴파일  (1) 2023.12.01
키워드 정리 [5] - 동적 할당  (1) 2023.12.01
키워드 정리 [4] - 구조체  (1) 2023.12.01
키워드 정리 [3] - 매크로  (1) 2023.12.01

+ Recent posts