스택 프레임에는 보통 이런 종류의 정보가 들어갑니다. (컴파일러/옵션에 따라 조금씩 달라질 수 있음)
┌────────────────────────────────────────┐
│ (상황에 따라) 인자/임시값 │ ← 스택 또는 레지스터
├────────────────────────────────────────┤
│ 반환 주소(Return Address) │ ← 끝나면 어디로 돌아갈지
├────────────────────────────────────────┤
│ 저장된 이전 프레임 포인터(BP/FP) │ ← 기준점(개념)
├────────────────────────────────────────┤
│ 지역 변수(Local) / 임시값 / 정렬 패딩 │
│ (필요 시) 저장된 레지스터(Spill) │
└────────────────────────────────────────┘
int Test(int a, int b) {
int c = a + b;
return c;
}
int main() {
Test(10, 20);
}
main()이 실행 중 Test(10, 20)을 호출하면, 스택에는 “Test 호출 1회분” 프레임이 추가됩니다.a, b, c가 잠깐 쓰이고, return을 만나면 프레임이 통째로 반납됩니다.호출 흐름을 스택으로 잡으면 이런 느낌입니다.
main() 실행 중
┌──────────────────────┐
│ main() 프레임 │
└──────────────────────┘
Test(10, 20) 호출
┌──────────────────────┐
│ main() 프레임 │
├──────────────────────┤
│ Test() 프레임 │ a=10, b=20, c=30 ...
└──────────────────────┘
Test() 종료(리턴) → Test() 프레임 반납 → main()으로 복귀
정리하면:
중요 포인트:
참고: Release 최적화에서는 프레임 포인터를 생략(FPO)하는 경우도 있어서,
디버깅 시 “항상 BP가 고정 기준”처럼 보이지 않을 수도 있습니다. (개념은 동일)
어떤 레지스터를 쓰는지는 OS/ABI에 따라 달라집니다.
예: Windows x64에서는 보통rcx,rdx,r8,r9부터 인자를 전달합니다.
여기서 초보자가 가장 많이 헷갈리는 포인트는 “0xCC 같은 값 = 카나리” 같은 혼동입니다.
디버그 패턴 값과 카나리(스택 쿠키) 는 목적이 다릅니다.
0xCC... 같은 값이 대표적입니다.또한 스택은 리턴 시 자동 초기화하지 않기 때문에, 반납된 영역을 다시 읽으면 “쓰레기 값”이 보일 수 있습니다.
스택 프레임을 이해하면 “분명히 더했는데 왜 원본이 안 바뀌지?” 같은 실수를 바로 설명할 수 있습니다.
| 구분 | 복사 전달 (Call by Value) | 참조/주소 전달 (Reference/Pointer) |
|---|---|---|
| 넘어가는 것 | 값이 복사됨 | 원본을 가리키는 정보(주소/참조) |
| 함수 내부에서 수정 | 원본 영향 없음 | 원본이 바뀜 |
// 복사: 원본 hp 변경 안 됨
void AddHp(int hp, int value) {
hp += value;
}
int main() {
int hp = 100;
AddHp(hp, 20);
cout << hp << '\n'; // 100 출력
}
위 코드에서 AddHp(hp, 20)은 “hp 변수 자체”를 넘기는 게 아니라,
hp에 들어있던 값(100) 을 복사해서 넘긴 것입니다.
// 참조: 원본 변경됨
int Test(int& a) {
a += 10;
return a;
}
int main() {
int x = 5;
Test(x);
cout << x << '\n'; // 15 출력
}
int AddHpNew(int hp, int value) {
return hp + value;
}
int main() {
int hp = 100;
hp = AddHpNew(hp, 20);
cout << hp << '\n'; // 120 출력
}
AddHp(hp, 20)에서 “넘어가는 것”은 hp 변수인가, hp의 값인가?하지만 “아무거나 스택에 막 올려도 된다”는 뜻은 아닙니다.
int big[1000000]; 같은 건 호출 1번에 스택을 크게 먹습니다.