CS โ stack overflow
๐ 05/08 โ Stack Overflow๋ ์ด๋ค ์ํฉ์์ ๋ฐ์ํ๋์?
๋ชจ์๋ฉด์ ์ฃผ์ : โStack Overflow๋ ์ด๋ค ์ํฉ์์ ๋ฐ์ํ๋์? ์ด๋ป๊ฒ ํด๊ฒฐํ ์ ์์๊น์?โ ๋ฐ์ ๋ฉ์ปค๋์ฆ โ 4๊ฐ์ง ์์ธ(๋ฌดํ ์ฌ๊ทยท๊น์ ์ฌ๊ทยท๊ฑฐ๋ ์ง์ญ ๋ณ์ยท์ํธ ํธ์ถ) โ ํ๋ซํผ๋ณ ์คํ ํฌ๊ธฐ โ ํด๊ฒฐ 5๊ฐ์ง(์ข ๋ฃ ์กฐ๊ฑดยท๋ฐ๋ณต๋ฌธยท๋ฉ๋ชจ์ด์ ์ด์ ยทTCOยท๋ช ์์ ์คํ) โ ์ปดํ์ผ๋ฌ/OS ์ฐจ์ ์กฐ์ โ ์ธ๋ฆฌ์ผ ์ปจ๋ฒค์ ๊น์ง
ํ์ต ์์ญ โ 19๋ฒ์์ ํ์๋ ๋ฉ๋ชจ๋ฆฌยทOS ํ๊ท
19๋ฒ์์ ํ๋ก์ธ์ค/์ค๋ ๋์ ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์์ ์ ๋ฆฌํ๋ฉด์ โ์ค๋ ๋๋ง๋ค ์๊ธฐ ์คํ์ ๊ฐ์ง๋คโ๋ ์ฌ์ค์ ๋ค๋ค๊ณ , Q14ยทQ15์์ ์คํ ์ค๋ฒํ๋ก๋ฅผ ์งง๊ฒ ์ง์์ต๋๋ค. 20๋ฒ์ ๊ทธ๊ฑธ ๋ณธ ์ฃผ์ ๋ก ๋์ด์ฌ๋ ค ์คํ์ด ์ ํ๊ณ๊ฐ ์๊ณ , ์ด๋ค ์ฝ๋๊ฐ ๊ทธ ํ๊ณ๋ฅผ ๋๊ฒ ๋ง๋ค๊ณ , ์ด๋ป๊ฒ ํํผํ๋์ง๋ฅผ ๋ค๋ฃน๋๋ค.
1
2
3
4
5
6
01๋ฒ ๋ฉ๋ชจ๋ฆฌ 4์์ญ (Code/Data/Heap/Stack) โ ์คํ = ํ๊ณ ์๋ ์์ญ
03๋ฒ new vs malloc (ํ vs ์คํ ๊ตฌ๋ถ) โ ํฐ ๋ฐ์ดํฐ๋ ํ์ผ๋ก
19๋ฒ ํ๋ก์ธ์ค vs ์ค๋ ๋ (์ค๋ ๋๋ง๋ค ๋
๋ฆฝ ์คํ) โ Q14ยทQ15์์ ์งง๊ฒ ๋ค๋ฃธ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
20๋ฒ Stack Overflow (โ
) โ ๋ณธ ์ฃผ์ ํ์ฅ
์ดํ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌยทํ์ด์ง / ํ ๋จํธํ / ๊ฐ๋ ํ์ด์ง
์คํ ์ค๋ฒํ๋ก๋ OS์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ์ ์ฑ ๊ณผ ์ปดํ์ผ๋ฌ์ ์ฝ๋ ์์ฑ ๊ฒฐ์ , ๊ทธ๋ฆฌ๊ณ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ๊ท ๊น์ด๊ฐ ๋ชจ๋ ๋ง๋๋ ์ง์ ์ ๋๋ค. ๊ทธ๋์ ํ ๋ฌธ์ ์์ OSยท์ปดํ์ผ๋ฌยท์๋ฃ๊ตฌ์กฐยท์ธ์ด ํ์ค์ด ๋ชจ๋ ๋ฑ์ฅํฉ๋๋ค.
๋ชจ์๋ฉด์ ๋ต๋ณ
์คํ ์ค๋ฒํ๋ก๋ ์ค๋ ๋์ ์คํ ์์ญ์ด ๋ฏธ๋ฆฌ ํ ๋น๋ ํ๊ณ๋ฅผ ์ด๊ณผํด ๋ ์ด์ ํจ์ ํธ์ถ ํ๋ ์์ ์์ ์ ์์ ๋ ๋ฐ์ํ๋ ๋ฉ๋ชจ๋ฆฌ ์ค๋ฅ์ ๋๋ค. ์คํ์ OS(์ด์์ฒด์ )๊ฐ ์ค๋ ๋๋ฅผ ๋ง๋ค ๋ ๊ณ ์ ํฌ๊ธฐ๋ก ์ก์์ฃผ๋ ์์ญ(Windows ๋ฉ์ธ ์ค๋ ๋ 1MB, Linux 8MB ๋ฑ)์ด๊ณ , ํจ์ ํธ์ถ์ด ํ ๋ฒ ์ผ์ด๋ ๋๋ง๋ค ๋ฆฌํด ์ฃผ์ยทํ๋ ์ ํฌ์ธํฐยท์ง์ญ ๋ณ์ยท์ธ์ ๋ณต์ฌ๋ณธ ๋ฑ์ ๋ด์ ์คํ ํ๋ ์์ด push(์๊ธฐ) ๋ฉ๋๋ค. ์ด SP(Stack Pointer, ์คํ ํฌ์ธํฐ)๊ฐ ์์ญ ๋(๊ฐ๋ ํ์ด์ง, guard page)์ ๋์ผ๋ฉด OS๊ฐ ์์ธ๋ฅผ ๋ฐ์์ํต๋๋ค.
๋ฐ์ ์ํฉ์ ํฌ๊ฒ ๋ค ๊ฐ์ง์ ๋๋ค.
- ์ฒซ์งธ, ๋ฌดํ ์ฌ๊ท(infinite recursion) โ base case(์ข ๋ฃ ์กฐ๊ฑด)๋ฅผ ๋น ๋จ๋ ค ํจ์๊ฐ ์๊ธฐ๋ฅผ ์์ํ ํธ์ถํ๋ ๊ฒฝ์ฐ์ ๋๋ค.
- ๋์งธ, ๋๋ฌด ๊น์ ์ฌ๊ท(deep recursion) โ ์ข ๋ฃ ์กฐ๊ฑด์ ์์ง๋ง ๊น์ด๊ฐ ์ปค์ ์คํ์ ์ฑ์๋ฒ๋ฆฌ๋ ๊ฒฝ์ฐ๋ก, naive(์๋ฐํ) ํผ๋ณด๋์น, ๊น์ ํธ๋ฆฌ DFS(Depth-First Search, ๊น์ด ์ฐ์ ํ์), ๊ทธ๋ํ ํ์์ด ๋ํ์ ์ ๋๋ค.
- ์
์งธ, ๊ฑฐ๋ํ ์ง์ญ ๋ณ์(large local variable) โ ํจ์ ์์
int arr[1000000]๊ฐ์ ๋์ฉ๋ ๋ฐฐ์ด์ ์ก์ผ๋ฉด ๊ทธ ํ ํจ์์ ํ๋ ์๋ง์ผ๋ก ์คํ์ด ํฐ์ง๋๋ค. - ๋ท์งธ, ๋ฌดํ ์ํธ ํธ์ถ(infinite mutual recursion) โ A๊ฐ B๋ฅผ ํธ์ถํ๊ณ B๊ฐ ๋ค์ A๋ฅผ ํธ์ถํ๋ ํจํด์ด ๋์์ด ์ด์ด์ง๋ ๊ฒฝ์ฐ์ ๋๋ค.
๋ฉ์ปค๋์ฆ์ ๋จ์ํฉ๋๋ค. ํจ์ ํธ์ถ โ ์คํ์ ํ๋ ์ push โ SP(Stack Pointer, ์คํ ํฌ์ธํฐ)๊ฐ ๋ฎ์ ์ฃผ์๋ก ์ด๋ โ SP๊ฐ ์คํ ์์ญ ํ๊ณ(guard page, ๊ฐ๋ ํ์ด์ง)์ ๋ฟ์ผ๋ฉด page fault(ํ์ด์ง ํดํธ, ๋ฉ๋ชจ๋ฆฌ ๋ณดํธ ์๋ฐ) โ OS๊ฐ STATUS_STACK_OVERFLOW(Windows ์คํ ์ค๋ฒํ๋ก ์์ธ ์ฝ๋, 0xC00000FD) ๋๋ SIGSEGV(Linux ์ธ๊ทธ๋ฉํ
์ด์
ํดํธ ์๊ทธ๋ 11)๋ก ํ๋ก์ธ์ค๋ฅผ ์ฃฝ์
๋๋ค. ๊ฐ๋ ํ์ด์ง๋ ์คํ ๋์ OS๊ฐ ๊น์๋๋ ๋ณดํธ ํ์ด์ง๋ก, ์ฌ๊ธฐ์ ์ ๊ทผํ๋ฉด ์ฆ์ ์์ธ๊ฐ ๋ฐ์ํ๋๋ก ํ์๋ผ ์์ด์ ๋ฌดํ ์ฌ๊ท๋ฅผ ๋น ๋ฅด๊ฒ ์ก์๋ผ ์ ์๊ฒ ํด์ค๋๋ค.
ํด๊ฒฐ์ฑ ์ ๋ค์ฏ ๊ฐ์ง๊ฐ ์์ต๋๋ค.
- ์ฒซ์งธ, base case(์ข ๋ฃ ์กฐ๊ฑด) ๊ฒ์ฆ โ ์ข ๋ฃ ์กฐ๊ฑด์ด ์ ํํ์ง, ์ฌ๊ท ํธ์ถ์ ์ธ์๊ฐ base case ์ชฝ์ผ๋ก ์ค์ด๋๋์ง ๋ค์ ๋ณด๋ ๊ฒ ๊ฐ์ฅ ๋จผ์ ์ ๋๋ค.
- ๋์งธ, ์ฌ๊ท๋ฅผ ๋ฐ๋ณต๋ฌธ(iteration)์ผ๋ก ๋ณํ โ ๋ชจ๋ ์ฌ๊ท๋ ์๋ฆฌ์ ๋ฐ๋ณต๋ฌธ + ๋ช ์์ ์คํ์ผ๋ก ๋ฐ๊ฟ ์ ์๊ณ , ์ด๋ฌ๋ฉด ์คํ์ ํ ํ๋ ์๋ง ์ฐ๊ฒ ๋ฉ๋๋ค.
- ์ ์งธ, ๋ฉ๋ชจ์ด์ ์ด์ (memoization, ๊ฒฐ๊ณผ ์บ์ฑ) / DP(Dynamic Programming, ๋์ ๊ณํ๋ฒ) โ ๊ฐ์ ๋ถ๋ถ ๋ฌธ์ ๋ฅผ ๋ฐ๋ณต ํธ์ถํ๋ ํจํด(naive ํผ๋ณด๋์น)์ ์บ์๋ฅผ ๋๋ฉด ํธ์ถ ํธ๋ฆฌ๊ฐ ํํํด์ ธ์ ๊น์ด๋ ์๊ฐ๋ณต์ก๋๋ ์ค์ด๋ญ๋๋ค(O(2^n) โ O(n)).
- ๋ท์งธ, TCO(Tail Call Optimization, ๊ผฌ๋ฆฌ ํธ์ถ ์ต์ ํ) โ ๋ง์ง๋ง์ ์๊ธฐ ํธ์ถ๋ง ํ๋ ํํ(tail call, ๊ผฌ๋ฆฌ ํธ์ถ)๋ ์ปดํ์ผ๋ฌ๊ฐ ์ ํ๋ก ๋ณํํด ์ ํ๋ ์ ์์ด ์ฒ๋ฆฌํ ์ ์๋๋ฐ, C++ ํ์ค์ TCO๋ฅผ ๋ณด์ฅํ์ง ์๊ณ GCC/Clang์ด ์ต์ ํ ๋น๋์์ ์ผ๋ถ ์ผ์ด์ค๋ง ์ ์ฉํฉ๋๋ค.
- ๋ค์ฏ์งธ, ๋ช
์์ ์คํ ์๋ฃ๊ตฌ์กฐ(explicit stack) โ
std::stack์ด๋std::vector๋ฅผ heap(ํ, ๋์ ๋ฉ๋ชจ๋ฆฌ)์ ๋๊ณ ๊ฑฐ๊ธฐ์ ์ํ๋ฅผ push/popํ๋ฉด ํธ์ถ ์คํ ๋์ ํ ์คํ์ ์ฐ๊ฒ ๋ฉ๋๋ค.
์ค๋ฌด์์ ๊ฐ์ฅ ๋ง์ด ๋ถ๋ชํ๋ ์ฌ๋ก๋ ๊น์ ํธ๋ฆฌ ์ํ์ ๊ฑฐ๋ํ ์ง์ญ ๋ฐฐ์ด์
๋๋ค. ํธ๋ฆฌ DFS(๊น์ด ์ฐ์ ํ์)๋ ๊น์ด๊ฐ ๋ง ๋จ๊ณ๋ง ๋์ด๊ฐ๋ ์ํํ๋ ๋ช
์์ ์คํ์ผ๋ก ๋ฐ๊พธ๊ฑฐ๋ BFS(Breadth-First Search, ๋๋น ์ฐ์ ํ์)๋ก ์ฐํํฉ๋๋ค. ๊ฑฐ๋ํ ๋ฐฐ์ด์ std::vector(ํ ๊ธฐ๋ฐ ๋์ ๋ฐฐ์ด)๋ std::unique_ptr<T[]>(ํ ๊ธฐ๋ฐ ๋จ๋
์์ ๋ฐฐ์ด)๋ก ์ฎ๊ธฐ๋ฉด ์ฆ์ ํด๊ฒฐ๋ฉ๋๋ค. ์ธ๋ฆฌ์ผ ์์ง์์ Tick()(๋งค ํ๋ ์ ํธ์ถ๋๋ ํจ์) ์์์ ๊น์ ์ฌ๊ท๋ฅผ ๋ง๋ค์ง ์๋ ๊ฒ ์ปจ๋ฒค์
์ด๊ณ , ๊น์ ์ฒ๋ฆฌ๊ฐ ํ์ํ๋ฉด FRunnable(์ธ๋ฆฌ์ผ ์์ปค ์ค๋ ๋ ์ธํฐํ์ด์ค)๋ก ์์ปค ์ค๋ ๋๋ฅผ ๋์ฐ๋ฉด์ FRunnableThread::Create์ InStackSize(์คํ ํฌ๊ธฐ) ์ธ์๋ฅผ ๋ช
์ํ ์ ์์ต๋๋ค. Blueprint(๋ธ๋ฃจํ๋ฆฐํธ, ๋น์ฃผ์ผ ์คํฌ๋ฆฝํ
)์์ ํจ์๊ฐ ์๊ธฐ๋ฅผ ๋ฌดํํ ํธ์ถํ๋ ๊ทธ๋ํ๋ฅผ ๋ง๋ค๋ฉด ์๋ํฐ๊ฐ ๊ทธ๋๋ก ํฌ๋์ํ๋ ๊ฒ ๊ฐ์ ๋ฉ์ปค๋์ฆ์
๋๋ค.
ํต์ฌ ๊ฐ๋
| ๋ถ๋ฅ | ํค์๋ | ํ ์ค ์ ์ |
|---|---|---|
| ์ ์ | Stack Overflow | ์ค๋ ๋ ์คํ ์์ญ์ด ํ๊ณ๋ฅผ ์ด๊ณผํด ๋ ํ๋ ์์ ์์ ์ ์๋ ์ํ |
| ย | ์คํ ํ๋ ์ (Stack Frame) | ํจ์ ํธ์ถ ํ ๋ฒ์ด ๋ง๋๋ ๋จ์ โ ๋ฆฌํด ์ฃผ์ยทํ๋ ์ ํฌ์ธํฐยท์ง์ญ ๋ณ์ยท์ธ์ |
| ย | SP (Stack Pointer) | ํ์ฌ ์คํ ์ต์๋จ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ ์ง์คํฐ. ํธ์ถ ์ ๊ฐ์(x86_64) |
| ๋ฉ๋ชจ๋ฆฌ | ๋ฉ๋ชจ๋ฆฌ 4์์ญ | Code / Data / Heap / Stack โ ์คํ๋ง LIFO ์๋ ๊ด๋ฆฌ (01๋ฒ ํ๊ท) |
| ย | ์คํ vs ํ | ์คํ์ ๋น ๋ฅด์ง๋ง ์๊ณ ์๋ / ํ์ ํฌ์ง๋ง ๋ช ์์ ํ ๋น (03๋ฒ ํ๊ท) |
| ย | ๊ฐ๋ ํ์ด์ง (Guard Page) | ์คํ ๋์ OS๊ฐ ๊น์๋ ๋ณดํธ ํ์ด์ง. ์ ๊ทผ ์ ์ฆ์ ์์ธ |
| ์ฌ๊ท | ์ฌ๊ท (Recursion) | ํจ์๊ฐ ์๊ธฐ ์์ ์ ํธ์ถํ๋ ํจํด |
| ย | base case (์ข ๋ฃ ์กฐ๊ฑด) | ์ฌ๊ท๋ฅผ ๋ฉ์ถ๋ ์กฐ๊ฑด. ๋น ์ง๋ฉด ๋ฌดํ ์ฌ๊ท |
| ย | ์ฌ๊ท ๊น์ด (Recursion Depth) | ๋์์ ์์ฌ ์๋ ์ฌ๊ท ํธ์ถ์ ์. ์คํ ๊น์ด์ ์ฃผ๋ฒ |
| ย | TCO (Tail Call Optimization) | ๊ผฌ๋ฆฌ ํธ์ถ์ ์ ํ๋ก ๋ณํํด ์ ํ๋ ์ ์์ด ์ฒ๋ฆฌ. C++ ํ์ค ๋ณด์ฅ X |
| ๋ฐ์ ์์ธ | ๋ฌดํ ์ฌ๊ท | base case ๋๋ฝ. ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ์คํ์ ๋ค ์ฑ์ |
| ย | ๋๋ฌด ๊น์ ์ฌ๊ท | ๊น์ด๊ฐ ํฐ ํธ๋ฆฌ/๊ทธ๋ํ DFS, naive ํผ๋ณด๋์น ๋ฑ |
| ย | ๊ฑฐ๋ํ ์ง์ญ ๋ณ์ | int arr[1000000] ๊ฐ์ ๋์ฉ๋ ๋ฐฐ์ด์ ์คํ์ ์ก์ |
| ย | ๋ฌดํ ์ํธ ํธ์ถ | AโBโAโBโฆ ๋ฌดํ ์ฌ์ดํด |
| ํ๋ซํผ | Windows ๋ฉ์ธ 1MB | ๊ธฐ๋ณธ ์คํ ํฌ๊ธฐ. /STACK:size ๋ง์ปค ์ต์
์ผ๋ก ๋ณ๊ฒฝ |
| ย | Linux ๋ฉ์ธ 8MB | ๊ธฐ๋ณธ๊ฐ. ulimit -s๋ก ์กฐํยท๋ณ๊ฒฝ |
| ย | ์์ปค ์ค๋ ๋ ์คํ | ๋ณดํต 1~2MB. pthread_attr_setstacksize / FRunnableThread::Create |
| ํด๊ฒฐ์ฑ | ์ฌ๊ท โ ๋ฐ๋ณต๋ฌธ | for/while๋ก ๋ณํ โ ์คํ ํ ํ๋ ์๋ง ์ฌ์ฉ |
| ย | ๋ฉ๋ชจ์ด์ ์ด์ / DP | ๊ฐ์ ๋ถ๋ถ ๋ฌธ์ ์บ์ฑ โ naive ํผ๋ณด๋์น O(2^n) โ O(n) |
| ย | ๋ช ์์ ์คํ ์๋ฃ๊ตฌ์กฐ | std::stack / std::vector๋ก ํธ์ถ ์คํ์ ํ์ผ๋ก ์ฎ๊น |
| ย | ๊ฑฐ๋ ๋ฐฐ์ด โ ํ | std::vector / std::unique_ptr<T[]>๋ก ์ด์ |
| ์ง๋จ | STATUS_STACK_OVERFLOW | Windows 0xC00000FD. SEH ์์ธ |
| ย | SIGSEGV | Linux. ์๊ทธ๋ 11. ๊ฐ๋ ํ์ด์ง ์ ๊ทผ ์ ๋ฐ์ |
| ย | ์ฝ์คํ ๋ถ์ | ๋๋ฒ๊ฑฐ๋ก ๋์ผ ํจ์๊ฐ ๋ฐ๋ณต ๋ฑ์ฅํ๋ฉด ์ฌ๊ท ํจํด ์ฆ์ ์๋ณ |
| ์ธ์ด/์์ง | C++ ํ์ค | ์คํ ํฌ๊ธฐยทTCO ๋ชจ๋ ํ์ค ๋ฏธ๋ณด์ฅ โ ๊ตฌํ์ฒด ์์กด |
| ย | JVM | -Xss ์ต์
์ผ๋ก ์ค๋ ๋ ์คํ ํฌ๊ธฐ ์ง์ . StackOverflowError ์์ธ |
| ย | Python | sys.setrecursionlimit(). ๊ธฐ๋ณธ 1000. ์ธํฐํ๋ฆฌํฐ ์คํ ํ๊ณ |
| ย | ์ธ๋ฆฌ์ผ FRunnable | FRunnableThread::Create์ InStackSize ์ธ์๋ก ๋ช
์ |
| ย | ์ธ๋ฆฌ์ผ BehaviorTree | ๊น์ด ์ ํ ์ปจ๋ฒค์ . ๋๋ฌด ๊น์ ํธ๋ฆฌ๋ ๋ถํ |
๋ชฉ์ฐจ
- ํต์ฌ ์์ฝ ์นด๋
- ํ ์ค ์ ์ โ Stack Overflow๋ ๋ฌด์์ธ๊ฐ
- ์คํ ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ โ ์ ํ๊ณ๊ฐ ์๋๊ฐ (01๋ฒ ํ๊ท)
- ๋ฐ์ ์์ธ 4๊ฐ์ง
- ํ๋ซํผ๋ณ ์คํ ํฌ๊ธฐ โ Windows / Linux / ์์ปค / ์ธ๋ฆฌ์ผ
- ์คํ vs ํ โ ํฐ ๋ฐ์ดํฐ๋ฅผ ํ์ผ๋ก ์ฎ๊ธฐ๊ธฐ (03๋ฒ ํ๊ท)
- ํด๊ฒฐ์ฑ 5๊ฐ์ง
- ์ปดํ์ผ๋ฌยทOS ์ฐจ์ โ ๊ฐ๋ ํ์ด์ง์ ์คํ ํฌ๊ธฐ ์กฐ์
- C++ ์ฝ๋ ์์ โ ํผ๋ณด๋์น / ๊ฑฐ๋ ๋ฐฐ์ด / ๋ช ์์ ์คํ
- ์ธ๋ฆฌ์ผ์์์ ์คํ ์ค๋ฒํ๋ก
- ๋๋ฒ๊น โ ์คํ ํธ๋ ์ด์ค๋ก ์ฌ๊ท ํจํด ์๋ณ
- ๊ผฌ๋ฆฌ์ง๋ฌธ ์์ ๊ฒฝ๋ก
- ํต์ฌ ์์ฝ ์นด๋ (์ฌ๊ฒ์ฌ)
- ํ๊ท ๋ค๋ฆฌ โ ๋ค๋ฅธ CS ํ์ผ ์ฐ๊ฒฐ
1. ํต์ฌ ์์ฝ ์นด๋
30์ด ๋ต๋ณ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Stack Overflow = ์ค๋ ๋ ์คํ ์์ญ(๊ณ ์ ํฌ๊ธฐ)์ด ํ๊ณ๋ฅผ ๋์ด ๋ ํ๋ ์์ ๋ชป ์๋ ์ํ.
ํจ์ ํธ์ถ๋ง๋ค SP๊ฐ ๊ฐ์ โ ๊ฐ๋ ํ์ด์ง ๋ฟ์ผ๋ฉด OS ์์ธ.
๋ฐ์ ์์ธ 4๊ฐ์ง:
โ ๋ฌดํ ์ฌ๊ท โ base case ๋๋ฝ
โก ๋๋ฌด ๊น์ ์ฌ๊ท โ naive ํผ๋ณด๋์น, ๊น์ ํธ๋ฆฌ DFS
โข ๊ฑฐ๋ํ ์ง์ญ ๋ณ์ โ int arr[1000000] ๊ฐ์ ๋์ฉ๋ ๋ฐฐ์ด
โฃ ๋ฌดํ ์ํธ ํธ์ถ โ AโBโAโB...
์คํ ํฌ๊ธฐ (๊ธฐ๋ณธ):
Windows ๋ฉ์ธ 1MB (/STACK:size ๋ง์ปค ์ต์
)
Linux ๋ฉ์ธ 8MB (ulimit -s)
์์ปค ์ค๋ ๋ 1~2MB (pthread_attr_setstacksize / FRunnableThread::Create)
ํด๊ฒฐ 5๊ฐ์ง:
โ ์ข
๋ฃ ์กฐ๊ฑด ์ ๊ฒ โ base case ๊ฒ์ฆ
โก ์ฌ๊ท โ ๋ฐ๋ณต๋ฌธ ๋ณํ โ ์คํ ํ ํ๋ ์๋ง ์ฌ์ฉ
โข ๋ฉ๋ชจ์ด์ ์ด์
/ DP โ naive O(2^n) โ O(n)
โฃ TCO (๋ณด์ฅ X) โ C++ ํ์ค ๋ฏธ๋ณด์ฅ, GCC/Clang ์ผ๋ถ
โค ๋ช
์์ ์คํ ์๋ฃ๊ตฌ์กฐ โ std::stack/std::vector๋ก ํ์ ์๋ฎฌ๋ ์ด์
์ง๋จ:
Windows: 0xC00000FD STATUS_STACK_OVERFLOW
Linux: SIGSEGV (๊ฐ๋ ํ์ด์ง ์ ๊ทผ)
๋๋ฒ๊ฑฐ ์ฝ์คํ โ ๋์ผ ํจ์ ๋ฐ๋ณต ๋ฑ์ฅ ์ ์ฌ๊ท ํจํด
ํฐ ๋ฐ์ดํฐ๋ ์คํ ๋์ ํ์ผ๋ก (3๋ฒ new/malloc ํ๊ท):
int arr[1000000] โ std::vector<int>(1000000) or std::unique_ptr<int[]>
๊ผฌ๋ฆฌ์ง๋ฌธ ์ฐ๊ฒฐ ๋งต
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Stack Overflow
โโโ ์คํ ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ โ ์ ํ๊ณ๊ฐ ์๋๊ฐ? (01๋ฒ ํ๊ท)
โ โโโ 4์์ญ ๋ชจ๋ธ โ Code/Data/Heap/Stack
โ โโโ ์คํ์ LIFO ์๋ ๊ด๋ฆฌ, ํฌ๊ธฐ ๊ณ ์
โโโ ๋ฐ์ ์์ธ 4๊ฐ์ง
โ โโโ ๋ฌดํ ์ฌ๊ท (base case ๋๋ฝ)
โ โโโ ๋๋ฌด ๊น์ ์ฌ๊ท (ํธ๋ฆฌ DFS, naive ํผ๋ณด๋์น)
โ โโโ ๊ฑฐ๋ํ ์ง์ญ ๋ณ์ (int arr[1000000])
โ โโโ ๋ฌดํ ์ํธ ํธ์ถ (AโBโAโB)
โโโ ํ๋ซํผ๋ณ ์คํ ํฌ๊ธฐ
โ โโโ Windows 1MB / Linux 8MB
โ โโโ ์์ปค ์ค๋ ๋ 1~2MB
โ โโโ ์ธ๋ฆฌ์ผ FRunnableThread::Create(InStackSize)
โโโ ์คํ vs ํ (03๋ฒ ํ๊ท)
โ โโโ ๋น ๋ฅด์ง๋ง ์์ ์คํ / ํฐ ํ
โ โโโ ํฐ ๋ฐ์ดํฐ โ std::vector / unique_ptr<T[]>
โโโ ํด๊ฒฐ์ฑ
5๊ฐ์ง
โ โโโ ์ข
๋ฃ ์กฐ๊ฑด ๊ฒ์ฆ
โ โโโ ๋ฐ๋ณต๋ฌธ ๋ณํ
โ โโโ ๋ฉ๋ชจ์ด์ ์ด์
/ DP (ํผ๋ณด๋์น O(2^n) โ O(n))
โ โโโ TCO (C++ ํ์ค ๋ณด์ฅ X)
โ โโโ ๋ช
์์ ์คํ ์๋ฃ๊ตฌ์กฐ (std::stack)
โโโ ์ปดํ์ผ๋ฌยทOS ์ฐจ์
โ โโโ ๊ฐ๋ ํ์ด์ง (Guard Page)
โ โโโ /STACK:size (Visual Studio ๋ง์ปค)
โ โโโ ulimit -s (Linux shell)
โ โโโ pthread_attr_setstacksize / FRunnableThread::Create
โโโ ์ง๋จ
โ โโโ Windows 0xC00000FD STATUS_STACK_OVERFLOW
โ โโโ Linux SIGSEGV
โ โโโ ์ฝ์คํ์์ ๋์ผ ํจ์ ๋ฐ๋ณต ๋ฑ์ฅ
โโโ ์ธ๋ฆฌ์ผ
โโโ FRunnableThread::Create โ InStackSize ์ธ์
โโโ BehaviorTree ๊น์ด ์ ํ ์ปจ๋ฒค์
โโโ Tick() ์ ๊น์ ์ฌ๊ท ๊ธ์ง
โโโ Blueprint ๋ฌดํ ํจ์ ํธ์ถ โ ์๋ํฐ ํฌ๋์
2. ํ ์ค ์ ์ โ Stack Overflow๋ ๋ฌด์์ธ๊ฐ
ํต์ฌ ํ ๋ฌธ์ฅ
Stack Overflow๋ ์ค๋ ๋์ ์คํ ์์ญ์ด ๋ฏธ๋ฆฌ ํ ๋น๋ ํ๊ณ๋ฅผ ์ด๊ณผํด์ ์ ํจ์ ํ๋ ์์ ์์ ์ ์์ ๋ ๋ฐ์ํ๋ ๋ฉ๋ชจ๋ฆฌ ์ค๋ฅ์ ๋๋ค.
ํ๋ฆ ํ๋์
1
2
3
4
5
6
7
8
9
ํจ์ ํธ์ถ
โ ์คํ์ ํ๋ ์ push (๋ฆฌํด ์ฃผ์ + ํ๋ ์ ํฌ์ธํฐ + ์ง์ญ ๋ณ์ + ์ธ์)
โ SP(์คํ ํฌ์ธํฐ) ๊ฐ์ (x86_64๋ ์คํ์ด ๋์ ์ฃผ์โ๋ฎ์ ์ฃผ์๋ก ์๋)
โ SP๊ฐ ์คํ ์์ญ ๋(๊ฐ๋ ํ์ด์ง)์ ๋ฟ์
โ ํ์ด์ง ํดํธ
โ OS๊ฐ ์์ธ ๋ฐ์
Windows: STATUS_STACK_OVERFLOW (0xC00000FD)
Linux: SIGSEGV (์๊ทธ๋ 11)
โ ํ๋ก์ธ์ค ์ข
๋ฃ (๋๋ SEH/์๊ทธ๋ ํธ๋ค๋ฌ ์ฒ๋ฆฌ)
์ โ์ค๋ฒํ๋กโ์ธ๊ฐ
์คํ์ ๊ณ ์ ํฌ๊ธฐ ์์ญ์ ๋๋ค. OS๊ฐ ์ค๋ ๋๋ฅผ ๋ง๋ค ๋ ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ ์์ ์ผ์ ๋ฒ์(์: 1MB)๋ฅผ ์คํ์ฉ์ผ๋ก ์ก์๋๊ณ , ๊ทธ ์์์ SP๊ฐ ์์๋๋ก ์์ง์ ๋๋ค. ํ ๋ฒ ์กํ ์คํ์ ์ผ๋ฐ์ ์ผ๋ก ํ์ฅ๋์ง ์์ต๋๋ค โ ๊ทธ๋์ ํ๊ณ๋ฅผ ๋์ผ๋ฉด โ๋์ณํ๋ ๋ค(overflow)โ๋ ์ด๋ฆ์ด ๋ถ์ต๋๋ค.
19๋ฒ์์ โ์ค๋ ๋๋ ์๊ธฐ๋ง์ ์คํ์ ๊ฐ์ง๋คโ๊ณ ํ๋๋ฐ, ๊ทธ ์๊ธฐ๋ง์ ์คํ์ด ๋ฐ๋ก ์ด ๊ณ ์ ํฌ๊ธฐ ์์ญ์ ๋๋ค. ๋ฉ์ธ ์ค๋ ๋์ ์์ปค ์ค๋ ๋๋ ๊ฐ์ ๋ค๋ฅธ ์คํ ์์ญ์ ๊ฐ์ง๋ฏ๋ก ์คํ ์ค๋ฒํ๋ก๋ ๊ทธ ์ค๋ ๋ ๋จ๋ ์ฌ๊ฑด์ ๋๋ค โ ๋ฉ์ธ ์ค๋ ๋๊ฐ ํฐ์ก๋ค๊ณ ์์ปค ์ค๋ ๋ ์คํ์ด ์ํฅ์ ๋ฐ์ง ์์ง๋ง, ๊ฐ์ ํ๋ก์ธ์ค๋ผ ๋ณดํต ํ๋ก์ธ์ค ์ ์ฒด๊ฐ ์ข ๋ฃ๋ฉ๋๋ค.
3. ์คํ ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ โ ์ ํ๊ณ๊ฐ ์๋๊ฐ (01๋ฒ ํ๊ท)
๋ฉ๋ชจ๋ฆฌ 4์์ญ ๋ค์ ๋ณด๊ธฐ
01๋ฒ์์ ์ ๋ฆฌํ 4์์ญ ๋ชจ๋ธ์ ๋ค์ ๊ฐ์ ธ์ต๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
๋์ ์ฃผ์ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Stack โ โ ํจ์ ํธ์ถ ์ push (์๋๋ก ์๋)
โ (์ง์ญ ๋ณ์ยท๋ฆฌํด ์ฃผ์) โ SP๊ฐ ๊ฐ๋ฆฌํด
โโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ ์คํ์ ์๋๋ก โ
โ โ
โ โ ํ์ ์๋ก โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Heap โ โ new/malloc (์๋ก ์๋)
โ (๋์ ํ ๋น) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ BSS / Data โ โ ์ ์ญยทstatic
โโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Code (Text) โ โ ์คํ ๋ช
๋ น์ด (read-only)
๋ฎ์ ์ฃผ์ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
์คํ์ 4๊ฐ์ง ํน์ง
- LIFO ์๋ ๊ด๋ฆฌ โ ํจ์ ์ง์
์ push, ๋ฆฌํด ์ pop. ์ปดํ์ผ๋ฌ๊ฐ prolog/epilog ์ฝ๋๋ก ์๋ ์์ฑ. ๋ช
์์
delete๋ถํ์. - ๊ณ ์ ํฌ๊ธฐ โ ์ค๋ ๋ ์์ฑ ์ OS๊ฐ ํ ๋ฒ์ ์ก๊ณ ๋ณดํต ํ์ฅ ์ ๋จ. (ํ์ฅ ๊ฐ๋ฅํ OS๋ ์์ง๋ง ํ๊ณ๊ฐ ์์)
- ๋น ๋ฆ โ SP ๊ฐ์ ํ ๋ฒ์ด๋ฉด ๋. ์บ์ ์นํ์ (์ฐ์ ๋ฉ๋ชจ๋ฆฌ). ํ ํ ๋น๋ณด๋ค 100๋ฐฐ ์ด์ ๋น ๋ฅธ ๊ฒฝ์ฐ๋.
- ์ค๋ ๋๋ณ ๋ ๋ฆฝ โ 19๋ฒ์์ ์ ๋ฆฌํ ๊ทธ๋๋ก. ๊ฐ์ ํ๋ก์ธ์ค ์ ์ค๋ ๋๋ค์ด ์๋ก์ ์คํ์ ๋ชป ๋ด.
์คํ ํ๋ ์ ํ ๊ฐ์ ๊ตฌ์กฐ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ํจ์ ํ ๋ฒ ํธ์ถ = ์คํ ํ๋ ์ ํ ๊ฐ
๋์ ์ฃผ์ โโโโโโโโโโโโโโโโโโโโโโโ
โ ์ธ์ (ํจ์ ์ธ์) โ caller๊ฐ ๋ฃ์ด์ฃผ๊ฑฐ๋ ๋ ์ง์คํฐ
โโโโโโโโโโโโโโโโโโโโโโโค
โ ๋ฆฌํด ์ฃผ์ โ call ๋ช
๋ น์ด๊ฐ ์๋์ผ๋ก push
โโโโโโโโโโโโโโโโโโโโโโโค โ FP (Frame Pointer, RBP)
โ ์ด์ ํ๋ ์ ํฌ์ธํฐ โ
โโโโโโโโโโโโโโโโโโโโโโโค
โ ์ง์ญ ๋ณ์ 1 โ
โ ์ง์ญ ๋ณ์ 2 โ
โ ... โ
โโโโโโโโโโโโโโโโโโโโโโโค
โ callee ์ ์ฅ ๋ ์ง์คํฐโ
๋ฎ์ ์ฃผ์ โโโโโโโโโโโโโโโโโโโโโโโ โ SP (Stack Pointer, RSP)
ํจ์๊ฐ ํ ๋ฒ ํธ์ถ๋ ๋๋ง๋ค ์ด ๋ธ๋ก์ด ํต์งธ๋ก push ๋ฉ๋๋ค. ์ง์ญ ๋ณ์๊ฐ ๋ง๊ฑฐ๋ ํฐ ๋ฐฐ์ด์ด ์์ผ๋ฉด ํ ํ๋ ์ ์์ฒด๊ฐ ์ปค์ง๊ณ , ํธ์ถ ๊น์ด๊ฐ ํฌ๋ฉด ํ๋ ์ ์๊ฐ ๋ง์์ง๋๋ค. ๋ ๋ค ์คํ ์ฌ์ฉ๋์ ์ฆ๊ฐ์ํค๋ฏ๋ก ๋ ๋ค ์ค๋ฒํ๋ก ์์ธ์ด ๋ฉ๋๋ค.
์ ํฌ๊ธฐ๋ฅผ ๋ฏธ๋ฆฌ ์ ํด๋๋
๊ฐ์ ์ฃผ์ ๊ณต๊ฐ ์์ ์คํ์ ๋ฌดํํ ํค์ธ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ํ ํ๋ก์ธ์ค์ ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ์ด 64๋นํธ๋ผ๋(์ด๋ก ์ 16EB), ๊ทธ ์์ ์ฝ๋ยท๋ฐ์ดํฐยทํยท์ฌ๋ฌ ์ค๋ ๋์ ์คํยท๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋งคํ ๋ฑ์ด ๋ชจ๋ ์๋ฆฌ ์ก์์ผ ํฉ๋๋ค. ์คํ์ ๋ฌด์ ํ ๋๋ ธ๋ค๊ฐ ๋ค๋ฅธ ์์ญ๊ณผ ์ถฉ๋ํ๋, OS๋ ์คํ๋ง๋ค ๋ฏธ๋ฆฌ ํ๊ณ๋ฅผ ์ ํด๋๊ณ ๊ทธ๊ฑธ ๋์ผ๋ฉด ์ฐจ๋ผ๋ฆฌ ์ฃฝ์ด๋ ์ ์ฑ ์ ํํฉ๋๋ค โ ๊ทธ๊ฒ ์คํ ์ค๋ฒํ๋ก ์์ธ์ ๋๋ค.
4. ๋ฐ์ ์์ธ 4๊ฐ์ง
์์ธ 1 โ ๋ฌดํ ์ฌ๊ท (base case ๋๋ฝ)
๊ฐ์ฅ ๋น ๋ฅด๊ฒ ์คํ์ ์ฑ์ฐ๋ ํจํด์ ๋๋ค. ์ข ๋ฃ ์กฐ๊ฑด์ ๋น ๋จ๋ฆฌ๊ฑฐ๋, ์ธ์๊ฐ ์ข ๋ฃ ์กฐ๊ฑด ์ชฝ์ผ๋ก ์ค์ด๋ค์ง ์์ผ๋ฉด ํจ์๊ฐ ๋์์ด ์๊ธฐ๋ฅผ ํธ์ถํฉ๋๋ค.
1
2
3
4
5
6
7
8
9
10
// ๋ฌดํ ์ฌ๊ท โ base case ์์
int Fail(int n) {
return Fail(n - 1) + 1; // ์ข
๋ฃ ์กฐ๊ฑด ์์ โ ์์ํ ํธ์ถ
}
// ๋ฌดํ ์ฌ๊ท โ ์ธ์๊ฐ ์ค์ง ์์
int AlsoFail(int n) {
if (n == 0) return 0; // base case๋ ์์ง๋ง
return AlsoFail(n); // ์ธ์ ๊ทธ๋๋ก โ ์ ๋ ๋๋ฌ ๋ชป ํจ
}
์์ญ๋ง ๋ฒ๋ง์ ์ฃฝ๊ธฐ ๋๋ฌธ์ ๋๋ฒ๊น ์ด ๋น ๋ฆ ๋๋ค. ์ฝ์คํ์ ๋ณด๋ฉด ๊ฐ์ ํจ์๊ฐ ๋์์ด ๋ฐ๋ณต๋ฉ๋๋ค.
์์ธ 2 โ ๋๋ฌด ๊น์ ์ฌ๊ท
์ข ๋ฃ ์กฐ๊ฑด์ ์ ํํ์ง๋ง ์ฌ๊ท ๊น์ด ์์ฒด๊ฐ ์คํ ํ๊ณ๋ณด๋ค ํฐ ๊ฒฝ์ฐ์ ๋๋ค.
๋ํ ์ฌ๋ก:
- naive ํผ๋ณด๋์น โ
fib(n) = fib(n-1) + fib(n-2). ๊น์ด๋ n์ด์ง๋ง ๊ฐ์ ๋ถ๋ถ ๋ฌธ์ ๋ฅผ ๋ฐ๋ณต ๊ณ์ฐํด ํธ์ถ ํธ๋ฆฌ๊ฐ O(2^n). - ๊น์ ํธ๋ฆฌ DFS โ ํธ๋ฆฌ ๊น์ด๊ฐ ๋ง ๋จ๊ณ ๋์ด๊ฐ๋ฉด ์ํ.
- ๊ทธ๋ํ ํ์ โ ์ฌ์ดํด์ด ์์ด๋ ๊ฒฝ๋ก๊ฐ ๊ธธ๋ฉด ์คํ ์นจ๋ฒ.
- JSON/XML ๊น์ ์ค์ฒฉ ํ์ฑ โ ๋ฐ์ดํฐ๊ฐ ๊ทธ๋๋ก ์คํ ๊น์ด๊ฐ ๋จ.
- ์ ๋ ฌ๋์ง ์์ ์ ๋ ฅ์ ๋ํ quicksort โ ์ต์ ์ ๊ฒฝ์ฐ O(n) ๊น์ด.
1
2
3
4
5
6
7
8
9
10
11
12
13
// ๊น์ ํธ๋ฆฌ DFS โ ๊น์ด๊ฐ ๋ง ๋จ๊ณ๋ฉด ์ํ
struct Node {
int value;
std::vector<Node*> children;
};
void DFS(Node* node) {
if (!node) return;
Process(node->value);
for (auto* child : node->children) {
DFS(child); // ๊น์ด = ํธ๋ฆฌ ๋์ด๋งํผ ์คํ ์ฌ์ฉ
}
}
์์ธ 3 โ ๊ฑฐ๋ํ ์ง์ญ ๋ณ์
ํธ์ถ ๊น์ด๋ ์์๋ ํ ํ๋ ์ ์์ฒด๊ฐ ๊ฑฐ๋ํ๋ฉด ํ ๋ฒ์ ์คํ์ ๋ค ์ธ ์ ์์ต๋๋ค.
1
2
3
4
5
6
7
8
void TooBig() {
int arr[1000000]; // 4MB! Windows ๋ฉ์ธ ์ค๋ ๋(1MB)์์ ์ง์
์ฆ์ ํฌ๋์
// 4MB > 1MB โ ์คํ ์ค๋ฒํ๋ก
}
void StillBad() {
char buffer[2 * 1024 * 1024]; // 2MB. Linux(8MB)๋ ์ด์ง๋ง ์์ปค ์ค๋ ๋๋ ์ํ
}
์ด ๊ฒฝ์ฐ ์ฝ์คํ์ ํ ์ค์ด๋ผ ๋๋ฒ๊น ๋จ์๊ฐ ์ฝํฉ๋๋ค. ํจ์ ์ง์ ์งํ ์ฃฝ๋๋ค๋ ์ ์ผ๋ก ์๋ณํฉ๋๋ค.
์์ธ 4 โ ๋ฌดํ ์ํธ ํธ์ถ
A๊ฐ B๋ฅผ ๋ถ๋ฅด๊ณ B๊ฐ ๋ค์ A๋ฅผ ๋ถ๋ฅด๋ ์ฌ์ดํด์ด ๋๋์ง ์๋ ํจํด์ ๋๋ค. ํ ํจ์๋ง ๋ณด๋ฉด ์ฌ๊ท๊ฐ ์๋๋ผ ๋ฐ๊ฒฌ์ด ๋ฆ์ด์ง๋๋ค.
1
2
3
4
5
void A();
void B();
void A() { B(); } // ์ข
๋ฃ ์กฐ๊ฑด ์๋ ์ํธ ํธ์ถ
void B() { A(); }
์ฝ์คํ์ AยทB๊ฐ ๋ฒ๊ฐ์ ๋ฑ์ฅํ๋ฉด ์ฆ์ ์๋ณ๋ฉ๋๋ค. ์ค๋ฌด์์ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ผ๋ฆฌ ์๋ก์ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํค๋ ํจํด(์: setter A๊ฐ B์ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํค๊ณ , ๊ทธ ์ด๋ฒคํธ๊ฐ ๋ค์ A์ setter๋ฅผ ๋ถ๋ฆ)์ผ๋ก ์์ฃผ ๋ง๋ฉ๋๋ค.
4์์ธ ๋น๊ต ํ
| ์์ธ | ํธ์ถ ๊น์ด | ํ ํ๋ ์ ํฌ๊ธฐ | ์ง๋จ ๋จ์ | ๋น๋ |
|---|---|---|---|---|
| ๋ฌดํ ์ฌ๊ท | ๋ฌดํ | ๋ณดํต | ์ฝ์คํ์ ๊ฐ์ ํจ์ ๋ฐ๋ณต | ์ด๋ณด์ ํํจ |
| ๋๋ฌด ๊น์ ์ฌ๊ท | ๋งค์ฐ ํผ | ๋ณดํต | ์ฝ์คํ ๊ธธ์ด + ๊น์ด ํจํด | ์๊ณ ๋ฆฌ์ฆ ์ฝ๋ ํํจ |
| ๊ฑฐ๋ ์ง์ญ ๋ณ์ | 1~์๊ฐ | ๊ฑฐ๋ | ํจ์ ์ง์ ์งํ ํฌ๋์ | ๊ฒ์/์๋ฎฌ๋ ์ด์ |
| ๋ฌดํ ์ํธ ํธ์ถ | ๋ฌดํ | ๋ณดํต | ์ฝ์คํ์ ๋ ํจ์ ๋ฒ๊ฐ์ | ์ด๋ฒคํธ ์์คํ |
5. ํ๋ซํผ๋ณ ์คํ ํฌ๊ธฐ โ Windows / Linux / ์์ปค / ์ธ๋ฆฌ์ผ
๊ธฐ๋ณธ ์คํ ํฌ๊ธฐ (๋ฉ์ธ ์ค๋ ๋)
| ํ๋ซํผ | ๊ธฐ๋ณธ ํฌ๊ธฐ | ๋ณ๊ฒฝ ๋ฐฉ๋ฒ |
|---|---|---|
| Windows | 1MB | ๋ง์ปค ์ต์
/STACK:reserve,commit |
| Linux | 8MB | ์
ธ ulimit -s [KB], ์ฝ๋ setrlimit(RLIMIT_STACK, ...) |
| macOS | 8MB (๋ฉ์ธ) / 512KB (์์ปค ๊ธฐ๋ณธ) | pthread_attr_setstacksize |
์์ปค ์ค๋ ๋ ์คํ ํฌ๊ธฐ
์์ปค ์ค๋ ๋๋ ๋ฉ์ธ๋ณด๋ค ์๊ฒ ์ก๋ ๊ฒ ์ผ๋ฐ์ ์ ๋๋ค. ์๋ง์ ์์ปค๋ฅผ ๋์์ผ ํ๋ ์๋ฒ์์ ์ค๋ ๋๋น 8MB๊ฐ ๋์ ๋๋ฉด ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ์ด ๋น ๋ฅด๊ฒ ์์ง๋ฉ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// pthread (Linux/macOS)
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 4 * 1024 * 1024); // 4MB๋ก ๋ช
์
pthread_create(&thread, &attr, RunFunc, nullptr);
pthread_attr_destroy(&attr);
// Windows
HANDLE thread = CreateThread(
nullptr, // ๋ณด์ ์์ฑ
4 * 1024 * 1024, // ์คํ ํฌ๊ธฐ 4MB
RunFunc,
nullptr,
0,
nullptr
);
// std::thread (C++) โ ํ์ค ์ธ์ ์์. OS ๊ธฐ๋ณธ๊ฐ ์ฌ์ฉ.
// ์ง์ ์ ์ดํ๋ ค๋ฉด ์ OS API ์ฌ์ฉํด์ผ ํจ.
std::thread t(RunFunc); // ์คํ ํฌ๊ธฐ ๋ช
์ ๋ถ๊ฐ (๊ตฌํ ์ ์)
์ธ๋ฆฌ์ผ FRunnableThread
์ธ๋ฆฌ์ผ์ ๋ฉํฐ ํ๋ซํผ์ด๋ผ ์์ฒด ์ถ์ํ๋ฅผ ์ ๊ณตํ๊ณ , ๊ทธ ์์ ์คํ ํฌ๊ธฐ๋ฅผ ๋ช ์ํ ์ ์๋ ์ธ์๊ฐ ์์ต๋๋ค.
1
2
3
4
5
6
7
8
9
// ์ธ๋ฆฌ์ผ์ FRunnableThread::Create
FRunnableThread* FRunnableThread::Create(
FRunnable* InRunnable,
const TCHAR* ThreadName,
uint32 InStackSize = 0, // โ 0์ด๋ฉด OS ๊ธฐ๋ณธ
EThreadPriority InThreadPri = TPri_Normal,
uint64 InThreadAffinityMask = FPlatformAffinity::GetNoAffinityMask(),
EThreadCreateFlags InCreateFlags = EThreadCreateFlags::None
);
InStackSize = 0์ด๋ฉด ํ๋ซํผ ๊ธฐ๋ณธ๊ฐ์ด ์ฐ์ด์ง๋ง, ๊น์ ์ฌ๊ท๊ฐ ํ์ํ ์์ปค(์: ํฐ ํธ๋ฆฌ ์ง๋ ฌํ ์์
์)๋ 4 * 1024 * 1024 ๊ฐ์ ๋ช
์ ๊ฐ์ ์ค๋๋ค.
๋ฉ๋ชจ๋ฆฌ ์ ์ ๊ด์
1
2
3
์ค๋ ๋ 100๊ฐ ร 1MB ์คํ = 100MB (๊ฐ์ ์ฃผ์ ๊ณต๊ฐ ์ ์ )
์ค๋ ๋ 100๊ฐ ร 8MB ์คํ = 800MB
์ค๋ ๋ 10000๊ฐ ร 1MB = 10GB โ 32๋นํธ ๊ฐ์ ๊ณต๊ฐ(4GB) ์ด๊ณผ
์๋ฒ์์ ์ค๋ ๋๋ฅผ ๋ง์ด ๋์ฐ๋ ค๋ฉด ์คํ ํฌ๊ธฐ๋ฅผ ์ค์ฌ์ผ ํฉ๋๋ค โ ๋จ, ๋๋ฌด ์ค์ด๋ฉด ์ผ๋ฐ ํจ์ ํธ์ถ์์๋ ์ค๋ฒํ๋ก๊ฐ ๋ฉ๋๋ค. ํธ๋ ์ด๋์คํ์ ๋๋ค.
6. ์คํ vs ํ โ ํฐ ๋ฐ์ดํฐ๋ฅผ ํ์ผ๋ก ์ฎ๊ธฐ๊ธฐ (03๋ฒ ํ๊ท)
03๋ฒ์์ new/malloc๋ก ํ์ ํ ๋นํ๋ ๋ฐฉ๋ฒ์ ์ ๋ฆฌํ๋๋ฐ, ๊ทธ๊ฒ ์คํ ์ค๋ฒํ๋ก ํํผ์ ๊ฐ์ฅ ์ง์ ์ ์ธ ํด๊ฒฐ์ฑ
์
๋๋ค.
๋น๊ต ํ
| ํญ๋ชฉ | ์คํ | ํ |
|---|---|---|
| ํ ๋น ๋ฐฉ์ | ํจ์ ์ง์ ์ ์๋ (SP ๊ฐ์) | new/malloc/std::vector ๋ช
์์ |
| ํด์ ๋ฐฉ์ | ํจ์ ๋ฆฌํด ์ ์๋ (SP ์ฆ๊ฐ) | delete/free ๋๋ RAII (์ค๋งํธ ํฌ์ธํฐ) |
| ์๋ | ๋งค์ฐ ๋น ๋ฆ (SP ๊ฐ์ 1ํ) | ๋น๊ต์ ๋๋ฆผ (free list ๊ฒ์ยท์ ๊ธ) |
| ํฌ๊ธฐ | ์ค๋ ๋๋น 1~8MB (๊ณ ์ ) | ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ ๊ฑฐ์ ์ ์ฒด (์ GB~์์ญ GB) |
| ์ฉ๋ | ์งง์ ์๋ช ยท์์ ๋ฐ์ดํฐยท์ฌ๊ท ํธ์ถ ํ๋ ์ | ๊ธด ์๋ช ยทํฐ ๋ฐ์ดํฐยท๋์ ํฌ๊ธฐ |
| ์๋ฌ | Stack Overflow | bad_alloc / OOM |
| ๋จํธํ | ๊ฑฐ์ ์์ (LIFO) | ๋จํธํ ๋ฐ์ ๊ฐ๋ฅ |
ํฐ ๋ฐ์ดํฐ๋ฅผ ์ฎ๊ธฐ๋ ํจํด
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// โ ์คํ โ 1MB ํ๋(Windows ๋ฉ์ธ) ์ด๊ณผ๋ก ์ฆ์ ํฌ๋์
void BadFunc() {
int arr[1000000]; // 4MB
}
// โ
std::vector โ ๋ฉํ๋ฐ์ดํฐ๋ง ์คํ, ์ค์ ๋ฐ์ดํฐ๋ ํ
void GoodFunc() {
std::vector<int> arr(1000000); // 16~24๋ฐ์ดํธ๋ง ์คํ, 4MB๋ ํ
}
// โ
std::unique_ptr<T[]> โ ์ผ์ ํฌ๊ธฐ ๋ฐฐ์ด์ RAII ์์ ๊ถ
void AlsoGood() {
auto arr = std::make_unique<int[]>(1000000);
}
// โ
์ ์ lifetime (์ ์ญ/static) โ Data/BSS ์์ญ์ด๋ผ ์คํ ๋ฌด๊ด
static int large_arr[1000000]; // 4MB but BSS ์์ญ, ์คํ ์ ์
ํ๋จ ๊ธฐ์ค (๊ฐ์ด)
- ์์ญ KB ์ดํ โ ์คํ OK
- ์๋ฐฑ KB ~ ์ MB โ ํ์ผ๋ก ์ฎ๊ธฐ๋ ๊ฒ ์์ (
std::vector) - ์์ญ MB ์ด์ โ ๋ฌด์กฐ๊ฑด ํ. ์ค๋ ๋ ์คํ ํฌ๊ธฐ ์์ฒด๋ณด๋ค ํผ.
03๋ฒ ํ๊ท:
newํ๋ํ๋ ์ง์ ๋ถ๋ฅด๊ธฐ๋ณด๋คstd::vector/std::unique_ptr๋ก RAII ํ์ฉํ๋ ๊ฒ ๋๊ธ๋งยท๋์ ๋ฐฉ์ง์ ์ข์ต๋๋ค. 9๋ฒ RAII์ 11๋ฒ ์ค๋งํธ ํฌ์ธํฐ์ ๋๊ธฐ ๊ทธ๋๋ก์ ๋๋ค.
7. ํด๊ฒฐ์ฑ 5๊ฐ์ง
ํด๊ฒฐ์ฑ 1 โ ์ข ๋ฃ ์กฐ๊ฑด ๊ฒ์ฆ (base case)
๊ฐ์ฅ ๋จผ์ ๋ด์ผ ํ ๊ฒ์ ์ฌ๊ท ํจ์์ base case๊ฐ ์ ํํ ์๋์ง, ์ฌ๊ท ํธ์ถ์ ์ธ์๊ฐ base case ์ชฝ์ผ๋ก ๋จ์กฐ๋กญ๊ฒ ์ค์ด๋๋์ง์ ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// โ ์ธ์๊ฐ ์ ์ค์ด๋ฆ
int Bad(int n) {
if (n == 0) return 0;
return Bad(n); // n ๊ทธ๋๋ก
}
// โ base case ๋๋ฌ ๋ชป ํจ (์์ ์
๋ ฅ)
int AlsoBad(int n) {
if (n == 0) return 1;
return AlsoBad(n - 1); // n=-1์ด๋ฉด ์์ํ -2, -3, ...
}
// โ
base case ๋ช
ํ + ์ธ์ ๋จ์กฐ ๊ฐ์ + ์์ ๋ฐฉ์ด
int Good(int n) {
if (n <= 0) return 1;
return Good(n - 1);
}
ํด๊ฒฐ์ฑ 2 โ ์ฌ๊ท๋ฅผ ๋ฐ๋ณต๋ฌธ์ผ๋ก ๋ณํ
์๋ฆฌ์ ๋ชจ๋ ์ฌ๊ท๋ ๋ฐ๋ณต๋ฌธ + ๋ช ์์ ์๋ฃ๊ตฌ์กฐ๋ก ๋ฐ๊ฟ ์ ์์ต๋๋ค. ๋จ์ ์ ํ ์ฌ๊ท(๊ผฌ๋ฆฌ ์ฌ๊ท)๋ for/while ํ ์ค๋ก ์ง์ ๋ณํ๋ฉ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
// ์ฌ๊ท โ ๊น์ด n
int FactRec(int n) {
if (n <= 1) return 1;
return n * FactRec(n - 1);
}
// ๋ฐ๋ณต๋ฌธ โ ์คํ ํ ํ๋ ์๋ง ์ฌ์ฉ
int FactIter(int n) {
int result = 1;
for (int i = 2; i <= n; ++i) result *= i;
return result;
}
ํด๊ฒฐ์ฑ 3 โ ๋ฉ๋ชจ์ด์ ์ด์ / DP
๊ฐ์ ๋ถ๋ถ ๋ฌธ์ ๋ฅผ ๋ฐ๋ณต ํธ์ถํ๋ ํจํด(naive ํผ๋ณด๋์น)์ ๊ฒฐ๊ณผ๋ฅผ ์บ์ฑํด์ ํธ์ถ ํธ๋ฆฌ๋ฅผ ํํํํฉ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// naive โ O(2^n), ์คํ ๊น์ด n
int FibNaive(int n) {
if (n < 2) return n;
return FibNaive(n-1) + FibNaive(n-2);
}
// ๋ฉ๋ชจ์ด์ ์ด์
โ O(n), ์คํ ๊น์ด n (์ฌ๊ท๋ ์ ์ง)
int FibMemo(int n, std::vector<int>& memo) {
if (n < 2) return n;
if (memo[n] != -1) return memo[n];
return memo[n] = FibMemo(n-1, memo) + FibMemo(n-2, memo);
}
// DP (๋ฐ๋ณต) โ O(n) ์๊ฐ, O(1) ๊ณต๊ฐ, ์คํ ํ ํ๋ ์
int FibDP(int n) {
if (n < 2) return n;
int a = 0, b = 1;
for (int i = 2; i <= n; ++i) {
int c = a + b;
a = b; b = c;
}
return b;
}
fib(40) ๊ธฐ์ค naive๋ ์ฝ 10์ต ๋ฒ ํธ์ถ, DP๋ 40๋ฒ ๋ฐ๋ณต์
๋๋ค. ์๊ฐ๋ณต์ก๋์ ์คํ ๊น์ด ๋ชจ๋ ์ค์ด๋ญ๋๋ค.
ํด๊ฒฐ์ฑ 4 โ Tail Call Optimization (TCO)
๋ง์ง๋ง ๋์์ด ์๊ธฐ ์์ ํธ์ถ์ธ ํํ(tail call)๋ ์ปดํ์ผ๋ฌ๊ฐ ์ ํ๋ก ๋ณํํ ์ ์์ต๋๋ค โ ์ ํ๋ ์์ ์ ๋ง๋ค๊ณ ํ์ฌ ํ๋ ์์ ์ฌ์ฌ์ฉํฉ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
// tail recursive โ ๋ง์ง๋ง์ ์๊ธฐ ํธ์ถ๋ง
int FactTail(int n, int acc = 1) {
if (n <= 1) return acc;
return FactTail(n - 1, n * acc); // โ ๋ง์ง๋ง ๋์์ด ์๊ธฐ ํธ์ถ
}
// non-tail โ return ํ์ ๊ณฑ์
์ด ๋ ์์ (TCO ๋ถ๊ฐ)
int FactNonTail(int n) {
if (n <= 1) return 1;
return n * FactNonTail(n - 1); // โ ํธ์ถ ํ ๊ณฑ์
โ ์ ํ๋ ์ ํ์
}
์ค์: C++ ํ์ค์ TCO๋ฅผ ๋ณด์ฅํ์ง ์์ต๋๋ค. GCC/Clang์ ์ต์ ํ ํ๋๊ทธ(-O2/-O3)์์ ์ผ๋ถ ์ผ์ด์ค๋ง ์ ์ฉํ๊ณ , MSVC๋ ๋ ๋ณด์์ ์
๋๋ค. TCO์ ์์กดํ ๊น์ ์ฌ๊ท ์ฝ๋๋ ๋๋ฒ๊ทธ ๋น๋์์ ๊ทธ๋๋ก ์ฃฝ์ ์ ์์ด ์ ๋ขฐํ ์ ์๋ ํด๊ฒฐ์ฑ
์
๋๋ค. ์์ ํ๋ ค๋ฉด ๋ฐ๋ณต๋ฌธ์ด๋ ๋ช
์์ ์คํ์ ์ฐ์ธ์.
Scheme/Haskell ๊ฐ์ ํจ์ํ ์ธ์ด๋ TCO๋ฅผ ํ์ค์ผ๋ก ๋ณด์ฅํฉ๋๋ค. C++์ ๊ทธ๋ ์ง ์๋ค๋ ๊ฒ ์ฐจ์ด์ ํต์ฌ.
ํด๊ฒฐ์ฑ 5 โ ๋ช ์์ ์คํ ์๋ฃ๊ตฌ์กฐ
std::stack์ด๋ std::vector๋ฅผ ํ์ ๋๊ณ ๊ฑฐ๊ธฐ์ ์ํ๋ฅผ push/popํ๋ฉด ํธ์ถ ์คํ ๋์ ํ ์คํ์ ์๋๋ค. ๊น์ด ํ๊ณ๊ฐ ์ฌ์ค์ ์ฌ๋ผ์ง๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// ์ฌ๊ท ํธ๋ฆฌ DFS โ ๊น์ด๊ฐ ๋ง ๋์ผ๋ฉด ์ํ
void DFSRec(Node* node) {
if (!node) return;
Process(node->value);
for (auto* child : node->children) {
DFSRec(child);
}
}
// ๋ช
์์ ์คํ โ ํธ์ถ ์คํ ๋์ ํ์ std::stack ์ฌ์ฉ
void DFSIter(Node* root) {
std::stack<Node*> stk;
stk.push(root);
while (!stk.empty()) {
Node* node = stk.top();
stk.pop();
if (!node) continue;
Process(node->value);
// ์ญ์ push๋ก ์ขโ์ฐ ์์ ์ ์ง
for (auto it = node->children.rbegin(); it != node->children.rend(); ++it) {
stk.push(*it);
}
}
}
std::stack์ ๋ด๋ถ์ ์ผ๋ก std::deque๋ฅผ ์ฐ๊ณ ๋ ๋ค ํ์ ๋
ธ๋๋ฅผ ์ก์ผ๋ฏ๋ก ์คํ ์์ญ๊ณผ ๋ฌด๊ดํฉ๋๋ค. ๊น์ด ํ๊ณ๋ ์ฌ์ค์ ๊ฐ์ฉ ํ ๋ฉ๋ชจ๋ฆฌ์
๋๋ค.
5ํด๊ฒฐ์ฑ ๋น๊ต ํ
| ํด๊ฒฐ์ฑ | ์ ์ฉ ์์ | ํจ๊ณผ | ํ๊ณ |
|---|---|---|---|
| ์ข ๋ฃ ์กฐ๊ฑด ๊ฒ์ฆ | ์ฝ๋ ์์ฑ ์ | ๋ฌดํ ์ฌ๊ท ์ฐจ๋จ | ๋๋ฌด ๊น์ ์ฌ๊ท์ ๋์ ์ ๋จ |
| ๋ฐ๋ณต๋ฌธ ๋ณํ | ๋ฆฌํฉํฐ๋ง | ์คํ ๊น์ด 1 | ์์ฐ์ค๋ฝ์ง ์์ ์ฝ๋๋ ์์ |
| ๋ฉ๋ชจ์ด์ ์ด์ / DP | ์๊ณ ๋ฆฌ์ฆ ์์ค | ์๊ฐ + ๊ณต๊ฐ ๋์ ๊ฐ์ | ๊ฐ์ ๋ถ๋ถ ๋ฌธ์ ํจํด์๋ง ์ ์ฉ |
| TCO | ์ปดํ์ผ๋ฌ ์์กด | ์ ํ๋ ์ ์์ | C++ ํ์ค ๋ฏธ๋ณด์ฅ, ๋๋ฒ๊ทธ ๋น๋ ์ํ |
| ๋ช ์์ ์คํ | ๋ฆฌํฉํฐ๋ง | ์ฌ์ค์ ๊น์ด ํ๊ณ ์์ | ์ฝ๋ ๊ธธ์ด ์ฆ๊ฐ, ๊ฐ๋ ์ฑ |
8. ์ปดํ์ผ๋ฌยทOS ์ฐจ์ โ ๊ฐ๋ ํ์ด์ง์ ์คํ ํฌ๊ธฐ ์กฐ์
๊ฐ๋ ํ์ด์ง (Guard Page)
OS๋ ์คํ ์์ญ ๋์ ๋ณดํธ์ฉ ํ์ด์ง๋ฅผ ํ ์ฅ ๊น์๋ก๋๋ค. ์ด ํ์ด์ง์ ์ ๊ทผํ๋ฉด ํ์ด์ง ํดํธ๊ฐ ์ฆ์ ๋ฐ์ํด ์คํ ์ค๋ฒํ๋ก๋ฅผ ๋น ๋ฅด๊ฒ ์ก์ต๋๋ค.
1
2
3
4
5
6
7
8
9
10
๋์ ์ฃผ์ โโโโโโโโโโโโโโโโโโ
โ ์คํ ์ฌ์ฉ ์ค โ
โ โ ์๋ผ๋ ๋ฐฉํฅ โ
โโโโโโโโโโโโโโโโโโค
โ ์์ง ๋ฏธ์ฌ์ฉ โ
โโโโโโโโโโโโโโโโโโค โ ๊ฐ๋ ํ์ด์ง (1~๋ช ํ์ด์ง)
โ GUARD PAGE โ ์ ๊ทผ ์ ์ฆ์ ์์ธ
โโโโโโโโโโโโโโโโโโค
โ (๋ค๋ฅธ ๋ฉ๋ชจ๋ฆฌ) โ
๋ฎ์ ์ฃผ์ โโโโโโโโโโโโโโโโโโ
๊ฐ๋ ํ์ด์ง๊ฐ ์๋ค๋ฉด ์คํ์ด ๋ค๋ฅธ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์นจ๋ฒํ๊ณ ๋์์ผ ์ ์ ์์ด์ ๋๋ฒ๊น ์ด ์ด๋ ต์ต๋๋ค. ๊ฐ๋ ํ์ด์ง ๋์ ์คํ ํ๊ณ ๋๋ฌ ์์ ์ ์ ํํ ์กํ๋๋ค.
Windows๋ ์ด ํ์ด์ง ํดํธ๋ฅผ STATUS_STACK_OVERFLOW(0xC00000FD) ๋ผ๋ SEH ์์ธ๋ก ๋ณํํฉ๋๋ค. Linux๋ SIGSEGV ์๊ทธ๋๋ก ๋ณด๋
๋๋ค.
์คํ ํฌ๊ธฐ ์กฐ์ (์๋)
Windows โ Visual Studio ๋ง์ปค
1
2
3
ํ๋ก์ ํธ ์์ฑ โ ๋ง์ปค โ ์์คํ
โ ์คํ ์์ฝ ํฌ๊ธฐ / ์คํ ์ปค๋ฐ ํฌ๊ธฐ
๋๋ ๋ช
๋ นํ: /STACK:reserve,commit
์) /STACK:8388608 โ 8MB ์์ฝ
reserve๋ ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ ์์ฝ๋, commit์ ์ค์ ๋ฌผ๋ฆฌ ๋ฉ๋ชจ๋ฆฌ ์ปค๋ฐ ์์๋. ๋ณดํต reserve๋ง ํค์๋๋ค.
Linux โ ์ ธ/์ฝ๋
1
2
3
# ์
ธ์์
ulimit -s # ํ์ฌ ์คํ ํฌ๊ธฐ (KB ๋จ์)
ulimit -s 16384 # 16MB๋ก ์ค์ (์์ ํ๋ก์ธ์ค์ ์ ์ฉ)
1
2
3
4
5
6
// ์ฝ๋์์
#include <sys/resource.h>
struct rlimit rl;
getrlimit(RLIMIT_STACK, &rl);
rl.rlim_cur = 16 * 1024 * 1024;
setrlimit(RLIMIT_STACK, &rl);
์์ปค ์ค๋ ๋ โ pthread
1
2
3
4
5
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 8 * 1024 * 1024);
pthread_create(&t, &attr, RunFunc, nullptr);
pthread_attr_destroy(&attr);
์ธ๋ฆฌ์ผ โ FRunnableThread
1
2
3
4
5
6
7
FRunnable* runnable = new FMyWorker();
FRunnableThread* thread = FRunnableThread::Create(
runnable,
TEXT("MyWorker"),
8 * 1024 * 1024, // ์คํ ํฌ๊ธฐ 8MB
TPri_Normal
);
์คํ ํฌ๊ธฐ ๋๋ฆฌ๊ธฐ vs ์๊ณ ๋ฆฌ์ฆ ๊ณ ์น๊ธฐ
์คํ ํฌ๊ธฐ ์กฐ์ ์ ์๊ธ์กฐ์น์ง ๊ทผ๋ณธ ํด๊ฒฐ์ด ์๋๋๋ค. ์๊ณ ๋ฆฌ์ฆ์ด O(n) ๊น์ด๋ฅผ ๊ฐ์ง๋ค๋ฉด ์ ๋ ฅ๋ง ๋ ์ปค์ง๋ฉด ๊ฒฐ๊ตญ ๋ค์ ํฐ์ง๋๋ค. ์๊ณ ๋ฆฌ์ฆ์ ๋ฐ๋ณต๋ฌธ์ด๋ ๋ช ์์ ์คํ์ผ๋ก ๋ฐ๊พธ๋ ๊ฒ ์ฐ์ ์ด๊ณ , ์คํ ํฌ๊ธฐ ์กฐ์ ์ ๋ง์ง๋ง ์๋จ์ ๋๋ค.
์์ธ์ ์ผ๋ก ์ ๋นํ ๊ฒฝ์ฐ:
- ์ผ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(์ปดํ์ผ๋ฌ, ์ธํฐํ๋ฆฌํฐ, ํธ๋ฆฌ/๊ทธ๋ํ ์๊ณ ๋ฆฌ์ฆ)๊ฐ ๊น์ ์ฌ๊ท๋ฅผ ๋ณธ์ง์ ์ผ๋ก ์๊ตฌ.
- ์ผํ์ฑ ๋๊ตฌ(์คํฌ๋ฆฝํธ, ๋ฐฐ์น ์ฒ๋ฆฌ)์์ ์๊ณ ๋ฆฌ์ฆ ์์ ๋น์ฉ์ด ํฌ๊ณ ์ ๋ ฅ์ด ์ ํ์ .
9. C++ ์ฝ๋ ์์ โ ํผ๋ณด๋์น / ๊ฑฐ๋ ๋ฐฐ์ด / ๋ช ์์ ์คํ
naive ํผ๋ณด๋์น (์คํ ํญ์ฆ + ์๊ฐ ํญ์ฆ)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
int FibNaive(int n) {
if (n < 2) return n;
return FibNaive(n - 1) + FibNaive(n - 2);
}
int main() {
std::cout << FibNaive(40) << std::endl;
// n=40: ์ฝ 10์ต ๋ฒ ํธ์ถ, ์๊ฐ ํญ์ฆ
// n=50: ๋ถ ๋จ์
// ๊น์ด ์์ฒด๋ n๊น์ง์ง๋ง ํธ์ถ ํธ๋ฆฌ๊ฐ O(2^n)
// ๊น์ด < 1MB ์คํ ํ๊ณ์ง๋ง, ์๊ฐ์ด ๋ ํฐ ๋ฌธ์
}
DP ํผ๋ณด๋์น (๋ฉ๋ชจ์ด์ ์ด์ , ์ฌ๊ท)
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <vector>
int FibMemo(int n, std::vector<int>& memo) {
if (n < 2) return n;
if (memo[n] != -1) return memo[n];
return memo[n] = FibMemo(n-1, memo) + FibMemo(n-2, memo);
}
int FibDPRec(int n) {
std::vector<int> memo(n + 1, -1);
return FibMemo(n, memo);
}
// ์๊ฐ O(n), ๊ณต๊ฐ O(n), ์คํ ๊น์ด O(n)
๋ฐ๋ณต๋ฌธ ํผ๋ณด๋์น (์ต์ โ ์คํ ํ ํ๋ ์)
1
2
3
4
5
6
7
8
9
10
int FibIter(int n) {
if (n < 2) return n;
int a = 0, b = 1;
for (int i = 2; i <= n; ++i) {
int c = a + b;
a = b; b = c;
}
return b;
}
// ์๊ฐ O(n), ๊ณต๊ฐ O(1), ์คํ ํ ํ๋ ์
๊ฑฐ๋ ์ง์ญ ๋ฐฐ์ด โ ํ (vector / unique_ptr)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <vector>
#include <memory>
// โ 4MB ์คํ ๋ฐฐ์ด โ Windows ๋ฉ์ธ(1MB)์์ ์ฆ์ ํฌ๋์
void BadFunc() {
int arr[1000000];
arr[0] = 0;
}
// โ
vector โ ์ปจํธ๋กค ๋ธ๋ก(๋ฉํ๋ฐ์ดํฐ)๋ง ์คํ, ์ค ๋ฐ์ดํฐ๋ ํ
void WithVector() {
std::vector<int> arr(1000000);
arr[0] = 0;
}
// โ
unique_ptr<T[]> โ RAII๋ก ์๋ ํด์
void WithUniquePtr() {
auto arr = std::make_unique<int[]>(1000000);
arr[0] = 0;
}
// โ
static โ Data/BSS ์์ญ์ด๋ผ ์คํ ๋ฌด๊ด (๋จ, ์ ์ญ ์ํ ์ฃผ์)
void WithStatic() {
static int arr[1000000]; // ํ ๋ฒ๋ง ์ด๊ธฐํ, BSS
arr[0] = 0;
}
std::stack์ผ๋ก ์ฌ๊ท โ ๋ฐ๋ณต ๋ณํ (ํธ๋ฆฌ ์ํ)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stack>
struct Node {
int value;
std::vector<Node*> children;
};
void Process(int v) { /* ... */ }
// ์ฌ๊ท โ ํธ๋ฆฌ ๊น์ด๊ฐ ๋ง ๋์ผ๋ฉด ์คํ ์ํ
void DFSRec(Node* node) {
if (!node) return;
Process(node->value);
for (auto* child : node->children) DFSRec(child);
}
// ๋ช
์์ ์คํ โ ๊น์ด ํ๊ณ = ๊ฐ์ฉ ํ ๋ฉ๋ชจ๋ฆฌ
void DFSIter(Node* root) {
if (!root) return;
std::stack<Node*> stk;
stk.push(root);
while (!stk.empty()) {
Node* node = stk.top();
stk.pop();
Process(node->value);
// ์์๋ค์ ์ญ์์ผ๋ก pushํด์ ์ขโ์ฐ ์์ ์ ์ง
for (auto it = node->children.rbegin(); it != node->children.rend(); ++it) {
if (*it) stk.push(*it);
}
}
}
๋ฌดํ ์ํธ ํธ์ถ (๋ฐ๋ก)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void A();
void B();
// ์ข
๋ฃ ์กฐ๊ฑด ์๋ ์ํธ ํธ์ถ โ ์คํ ์ค๋ฒํ๋ก
void A() { B(); }
void B() { A(); }
// ์์ โ ์นด์ดํฐ/์กฐ๊ฑด์ผ๋ก ์ข
๋ฃ
void A2(int depth);
void B2(int depth);
void A2(int depth) {
if (depth <= 0) return; // ์ข
๋ฃ ์กฐ๊ฑด
B2(depth - 1);
}
void B2(int depth) {
if (depth <= 0) return;
A2(depth - 1);
}
10. ์ธ๋ฆฌ์ผ์์์ ์คํ ์ค๋ฒํ๋ก
FRunnableThread::Create์ ์คํ ํฌ๊ธฐ ์ธ์
์ธ๋ฆฌ์ผ์ ์์ปค ์ค๋ ๋ ์ถ์ํ์ ์คํ ํฌ๊ธฐ ๋ช ์ ์ธ์๋ฅผ ๋๊ณ ์์ต๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class FMyHeavyWorker : public FRunnable {
public:
virtual uint32 Run() override {
ProcessLargeTree(); // ๊น์ ์ฌ๊ท๋ฅผ ์ธ ์ ์๋ ์์
return 0;
}
// ...
};
void StartWorker() {
FMyHeavyWorker* w = new FMyHeavyWorker();
FRunnableThread::Create(
w,
TEXT("HeavyWorker"),
8 * 1024 * 1024, // 8MB ์คํ (๊ธฐ๋ณธ๊ฐ๋ณด๋ค ํค์)
TPri_Normal
);
}
InStackSize = 0์ด๋ฉด OS ๊ธฐ๋ณธ๊ฐ์ ๊ทธ๋๋ก ์๋๋ค. ๊น์ ํธ๋ฆฌ/๊ทธ๋ํ ์๊ณ ๋ฆฌ์ฆ์ ์์ปค์์ ๋๋ฆด ์ผ์ด ์์ผ๋ฉด ๋ช
์์ ์ผ๋ก ํค์ฐ๋ ๊ฒ ์์ ํฉ๋๋ค.
BehaviorTree ๊น์ด ์ ํ ์ปจ๋ฒค์
์ธ๋ฆฌ์ผ์ BehaviorTree๋ ๋ ธ๋ ํธ๋ฆฌ๋ฅผ ํ๊ฐํ๋ฉด์ ํจ์ ํธ์ถ ์คํ์ ์ฌ์ฉํฉ๋๋ค. ํธ๋ฆฌ ๊น์ด๊ฐ ๋๋ฌด ํฌ๋ฉด ํ๊ฐ ๋์ค ์คํ ์ค๋ฒํ๋ก๊ฐ ๋ฐ์ํฉ๋๋ค. ์ปจ๋ฒค์ :
- ํธ๋ฆฌ ๊น์ด๋ฅผ ํฉ๋ฆฌ์ ์ธ ๋ฒ์(๋ณดํต ์์ญ ๋จ๊ณ ์ด๋ด)๋ก ์ ์ง.
- ๊น์ ์์ฌ๊ฒฐ์ ์ด ํ์ํ๋ฉด ์๋ธํธ๋ฆฌ(BTSubtree)๋ก ๋ถํ ํด์ ํธ๋ฆฌ ํธ์ถ์ด ๋ถ์ฐ๋๋๋ก.
- BehaviorTree ํ๊ฐ๊ฐ ๋ฉ์ธ ๊ฒ์ ์ค๋ ๋์์ ์ผ์ด๋๋ค๋ ์ ๋ ๋ณ์ โ ๊ฒ์ ์ค๋ ๋ ์คํ์ ์ด๋ฏธ ์์ง์ด ๋ง์ด ์ ์ ํฉ๋๋ค.
Tick() ์์์ ๊น์ ์ฌ๊ท ๊ธ์ง
AActor::Tick()์ ๋งค ํ๋ ์(60fps ๊ธฐ์ค 16.6ms๋ง๋ค) ํธ์ถ๋๋ ํจ์๋ก, ๊ฒ์ ์ค๋ ๋ ์คํ ์์ ์์ง์ด ์ด๋ฏธ ๊น์ ์ฝ ์ฒด์ธ์ ์์๋ ์ํ์
๋๋ค. ์ฌ๊ธฐ์ ๊น์ ์ฌ๊ท๋ฅผ ์ถ๊ฐํ๋ฉด ํ์์ ๋ฉ์ฉกํ๋ค๊ฐ ํน์ ์
๋ ฅ์์ ๊ฐ์๊ธฐ ํฌ๋์ํฉ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// โ Tick์์ ๊น์ ์ฌ๊ท
void AMyActor::Tick(float DeltaTime) {
Super::Tick(DeltaTime);
ProcessTreeRecursive(RootNode); // ํธ๋ฆฌ ๊น์ด๊ฐ ํฌ๋ฉด ๊ฒ์ ์ค๋ ๋ ์คํ ์ค๋ฒํ๋ก
}
// โ
๋ช
์์ ์คํ ๋๋ BFS
void AMyActor::Tick(float DeltaTime) {
Super::Tick(DeltaTime);
ProcessTreeIterative(RootNode);
}
// โ
๋๋ ์์ปค๋ก ๋ถ๋ฆฌ (์คํ ํฌ๊ธฐ ๋ช
์)
void AMyActor::BeginPlay() {
Super::BeginPlay();
auto* worker = new FTreeProcessor(RootNode);
FRunnableThread::Create(worker, TEXT("TreeProc"), 8*1024*1024);
}
Blueprint ๋ฌดํ ํจ์ ํธ์ถ โ ์๋ํฐ ํฌ๋์
Blueprint Visual Scripting์์ ํจ์ ๋ ธ๋๊ฐ ์๊ธฐ๋ฅผ ํธ์ถํ๋ ๊ทธ๋ํ(๋๋ ๋ ํจ์๊ฐ ์๋ก ํธ์ถ)๋ฅผ ๋ง๋ค๋ฉด, ์คํ ์ C++ ํจ์ ํธ์ถ์ด ๊ทธ๋๋ก ๊น์ด์ ธ ์๋ํฐ๊ฐ ํต์งธ๋ก ํฌ๋์ํฉ๋๋ค. ์ด๊ฒ ๊ฐ์ ๋ฉ์ปค๋์ฆ์ ๋๋ค โ Blueprint ๊ฐ์ ๋จธ์ ์ด ์ฌ์ฉ์๊ฐ ์์ฑํ ๊ทธ๋ํ๋ฅผ ๋ฐ๋ผ ์ค์ C++ ํจ์ ํธ์ถ์ ์๊ธฐ ๋๋ฌธ.
๋ฐฉ์ด์ฑ :
- Blueprint์์ ํจ์๊ฐ ์๊ธฐ๋ฅผ ํธ์ถํ๋ฉด ๋นจ๊ฐ ๊ฒฝ๊ณ ํ์๊ฐ ๋์ด โ ๋ฌด์ํ์ง ๋ง ๊ฒ.
- ๊น์ ๋ฐ๋ณต์ด ํ์ํ๋ฉด for/while ๋ ธ๋ ๋๋ ๋ฐ๋ณต ํ์ด๋จธ(timer) ์ฌ์ฉ.
- ์๊ฐ ํธ์ถ์ด ์ ๋ง ํ์ํ๋ฉด ๊น์ด ์นด์ดํฐ๋ก ์ข ๋ฃ ์กฐ๊ฑด์ ๋ช ์.
์ธ๋ฆฌ์ผ GC์ ์คํ์ ๊ด๊ณ
์ธ๋ฆฌ์ผ GC๊ฐ ๊ฐ์ฒด ๊ทธ๋ํ๋ฅผ ์ถ์ ํ ๋๋ ํธ์ถ ์คํ์ ์ฌ์ฉํ ์ ์์ต๋๋ค โ ๋งค์ฐ ๊น์ ๊ฐ์ฒด ์ฐธ์กฐ ๊ทธ๋ํ(๊ฑฐ๋ํ UObject ํธ๋ฆฌ)๋ GC ํจ์ค์์ ์คํ ์ค๋ฒํ๋ก ์ํ์ ์ผ์ผํฌ ์ ์์ต๋๋ค. ์์ง์ ๋ณดํต ๋ช
์์ ์คํ/ํ๋ก ์ฐํํ์ง๋ง, ์ฌ์ฉ์ ์ฝ๋์์ GC ์ฝ๋ฐฑ(AddReferencedObjects ๋ฑ) ์์์ ๊น์ ์ฌ๊ท๋ฅผ ๋ง๋ค๋ฉด ๊ฐ์ ๋ฌธ์ ๊ฐ ์ฌ๋ฐํฉ๋๋ค.
11. ๋๋ฒ๊น โ ์คํ ํธ๋ ์ด์ค๋ก ์ฌ๊ท ํจํด ์๋ณ
Windows โ STATUS_STACK_OVERFLOW (0xC00000FD)
ํฌ๋์ ๋ค์ด์ผ๋ก๊ทธ๋ ๋๋ฒ๊ฑฐ์ ํ์๋๋ ์ฝ๋์
๋๋ค. SEH(Structured Exception Handling) ์์ธ๋ผ __try/__except๋ก ๋ถ๋ถ์ ์ผ๋ก ์ก์ ์๋ ์์ง๋ง, ๊ถ์ฅ์ ์๋๋๋ค(์คํ์ด ๊ฑฐ์ ๋ค ์ฐฌ ์ํ๋ผ ํธ๋ค๋ฌ ์คํ ์์ฒด๊ฐ ์ํ).
Linux โ SIGSEGV (์๊ทธ๋ 11)
๋ฆฌ๋ ์ค์์ ๊ฐ๋ ํ์ด์ง ์ ๊ทผ์ด ์ผ๋ฐ segfault์ ๊ฐ์ ์๊ทธ๋๋ก ๋ณด๊ณ ๋ฉ๋๋ค. ๊ทธ๋์ SIGSEGV๊ฐ ๋ด์ ๋ ์ฝ์คํ์ ๋ณด๊ณ ๊น์ด๊ฐ ๋น์ ์์ ์ผ๋ก ๊ธธ๊ฑฐ๋ ๊ฐ์ ํจ์๊ฐ ๋ฐ๋ณต๋๋ฉด ์คํ ์ค๋ฒํ๋ก๋ก ํ์ ํฉ๋๋ค.
๋๋ฒ๊ฑฐ ์ฝ์คํ ๋ถ์ ํจํด
๋ฌดํ ์ฌ๊ท
1
2
3
4
5
#0 Bad(int) at main.cpp:5
#1 Bad(int) at main.cpp:6
#2 Bad(int) at main.cpp:6
#3 Bad(int) at main.cpp:6
... (์๋ง ์ค ๋ฐ๋ณต) ...
๊ฐ์ ํจ์๊ฐ ๋์์ด ๋ฐ๋ณต โ ๋ฌดํ ์ฌ๊ท.
๋๋ฌด ๊น์ ์ฌ๊ท (ํธ๋ฆฌ DFS)
1
2
3
4
5
6
#0 DFS(Node*) at tree.cpp:42
#1 DFS(Node*) at tree.cpp:42
#2 DFS(Node*) at tree.cpp:42
... (๋ง~์๋ง ์ค) ...
#9999 DFS(Node*) at tree.cpp:42
#10000 main() at main.cpp:10
๊ฐ์ ํจ์์ง๋ง ํธ์ถ ๊น์ด๊ฐ ๋ง~์๋ง ๋จ์ โ ๊น์ ์ฌ๊ท.
๋ฌดํ ์ํธ ํธ์ถ
1
2
3
4
5
#0 A() at main.cpp:3
#1 B() at main.cpp:7
#2 A() at main.cpp:3
#3 B() at main.cpp:7
... (๋ฐ๋ณต) ...
๋ ํจ์๊ฐ ๋ฒ๊ฐ์ ๋ฑ์ฅ โ ์ํธ ํธ์ถ.
๊ฑฐ๋ ์ง์ญ ๋ณ์
1
2
#0 TooBig() at main.cpp:5
#1 main() at main.cpp:20
์ฝ์คํ์ด ์งง์. ํจ์ ์ง์
์งํ ํฌ๋์. ์ฝ๋๋ฅผ ๋ณด๋ฉด int arr[1000000] ๊ฐ์ ๋์ฉ๋ ์ง์ญ.
๋๋ฒ๊น ๋๊ตฌ
- Visual Studio: ์ฝ์คํ ์ฐฝ โ ์คํ ์ค๋ฒํ๋ก ๋ฐ์ ์ ์ฝ์คํ์ด 1๋ง ์ค ์ด์์ด๋ฉด ๊ทธ๋๋ก ๋ณด์ฌ์ค.
- GDB:
bt(backtrace) โ ๋๋ฌด ๊ธธ๋ฉดbt 50์ผ๋ก ์์ 50ํ๋ ์๋ง. - AddressSanitizer /
-fsanitize=stack: ์ผ๋ถ ์ผ์ด์ค(์ปดํ์ผ ์ ๊ฒฐ์ ๊ฐ๋ฅํ ํฐ ๋ฐฐ์ด)์์ ์ฌ์ ๊ฒ์ถ ๊ฐ๋ฅ. - ์ธ๋ฆฌ์ผ: ํฌ๋์ ๋ฆฌํฌํฐ๊ฐ ์ฝ์คํ์ ์๋ ์์ง.
.dmpํ์ผ๋ก ์ฌํ ๋ถ์.
12. ๊ผฌ๋ฆฌ์ง๋ฌธ ์์ ๊ฒฝ๋ก
Q1. โ์ ์คํ์ ํฌ๊ธฐ๊ฐ ์ ํด์ ธ ์๋์?โ
๊ฐ์ ์ฃผ์ ๊ณต๊ฐ์ ๋ฌดํํ ์ธ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ํ ํ๋ก์ธ์ค์ ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ ์์๋ ์ฝ๋ยท๋ฐ์ดํฐยทํยท์ฌ๋ฌ ์ค๋ ๋์ ์คํยท๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋งคํ์ด ๋ชจ๋ ์๋ฆฌ ์ก์์ผ ํ๊ณ , ์คํ์ ๋ฌด์ ํ์ผ๋ก ๋๋ ธ๋ค๊ฐ ๋ค๋ฅธ ์์ญ๊ณผ ์ถฉ๋ํฉ๋๋ค. ๊ทธ๋์ OS๋ ์ค๋ ๋ ์์ฑ ์์ ์ ๊ณ ์ ํฌ๊ธฐ ์์ญ์ ์ก๊ณ , ๊ทธ ํ๊ณ๋ฅผ ๋์ผ๋ฉด ์ฐจ๋ผ๋ฆฌ ์ฃฝ์ด๋ ์ ์ฑ ์ ํํฉ๋๋ค โ ๊ทธ๊ฒ ์คํ ์ค๋ฒํ๋ก ์์ธ์ ๋๋ค. ๋ ํ๋์ ์ด์ ๋ ๋ฌดํ ์ฌ๊ท ๊ฐ์ ๋ฒ๊ทธ๋ฅผ ๋น ๋ฅด๊ฒ ์ก๊ธฐ ์ํจ์ ๋๋ค โ ํ๊ณ๊ฐ ์์ผ๋ฉด ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ์ด ๋ค ์ฐฐ ๋๊น์ง swap ๊ณผ ํ์ด์ง ํดํธ๋ก ์์คํ ์ ์ฒด๊ฐ ๋๋ ค์ง๋ค ์ฃฝ์ง๋ง, ํ๊ณ๊ฐ ์์ผ๋ฉด ๊ณง๋ฐ๋ก ๋ช ํํ ์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค.
Q2. โ์คํ๊ณผ ํ์ ํฌ๊ธฐ ์ฐจ์ด๋ ์ ๋๋์?โ
์ฉ๋๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ๋๋ค. ์คํ์ ํจ์ ํธ์ถ ๋จ์๋ก LIFO ์๋ ๊ด๋ฆฌ๋๊ณ ์งง์ ์๋ช ยท์์ ๋ฐ์ดํฐ์ ์ต์ ํ๋ผ ์์ด์ ๋น ๋ฅธ ๋์ ์๊ฒ ์ก์ต๋๋ค(๋ณดํต 1~8MB). ํ์ ๋ช ์์ ํ ๋น์ผ๋ก ์์์ ์๋ช ยท์์์ ํฌ๊ธฐ๋ฅผ ๋ค๋ค์ผ ํ๋ ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ ๊ฑฐ์ ์ ์ฒด(์ GB~์์ญ GB)๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ์ก์ต๋๋ค. ์คํ์ด ์์ ๋ ๋ค๋ฅธ ์ด์ ๋ ์๋ง์ ์ค๋ ๋๋ฅผ ๋์ฐ๋ ค๋ฉด ์คํ์ด ์์์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค โ ์ค๋ ๋ 1๋ง ๊ฐ์ ์คํ 8MB๋ฉด 80GB๊ฐ ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ์์ ์ ์ ๋์ด 32๋นํธ ํ๊ฒฝ์์ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
Q3. โ์ฌ๊ท๊ฐ ๋ฌด์กฐ๊ฑด ๋์๊ฐ์?โ
์๋์, ์ฌ๊ท๋ ๋ฌธ์ ํํ์ ์์ฐ์ค๋ฌ์ด ๋๊ตฌ์ ๋๋ค. ํธ๋ฆฌยท๊ทธ๋ํยท๋ถํ ์ ๋ณต(merge sort, quicksort)์ ์ฌ๊ท๋ก ํํํ๋ ๊ฒ ๊ฐ๋ ์ฑ๋ ์ข๊ณ ์ ํํฉ๋๋ค. ๋ฌธ์ ๋ ๊น์ด ํ๊ณ์ ํจ์ ํธ์ถ ์ค๋ฒํค๋์ ๋๋ค. ๊น์ด๊ฐ ์๊ณ (๋ณดํต ์๋ฐฑ ์ดํ) ํ ํ๋ ์ ํฌ๊ธฐ๊ฐ ํ๋ฒํ๋ฉด ์ฌ๊ท๊ฐ ๋ ๋ช ํํฉ๋๋ค. ๊น์ด๊ฐ ํฌ๊ฑฐ๋ ๊ฐ์ ๋ถ๋ถ ๋ฌธ์ ๋ฅผ ๋ฐ๋ณต ํธ์ถํ๋ฉด(ํผ๋ณด๋์น) ๊ทธ๋ ๋ฐ๋ณต๋ฌธ/๋ฉ๋ชจ์ด์ ์ด์ /๋ช ์์ ์คํ์ผ๋ก ๋ฐ๊ฟ๋๋ค. โ์ฌ๊ท = ๋์จโ์ด ์๋๋ผ โ๊น์ด๊ฐ ์๊ณ ๋ฆฌ์ฆ ์ ๋ ฅ์ ๋น๋กํ๋ฉด ์ํโ์ด ์ ํํ ๊ธฐ์ค์ ๋๋ค.
Q4. โTail Call Optimization์ด ์ ํํ ๋ญ๊ฐ์?โ
ํจ์์ ๋ง์ง๋ง ๋์์ด ์๊ธฐ ์์ (๋๋ ๋ค๋ฅธ ํจ์)์ ํธ์ถ์ธ ๊ฒฝ์ฐ, ์ปดํ์ผ๋ฌ๊ฐ ์ ์คํ ํ๋ ์์ ๋ง๋ค์ง ์๊ณ ํ์ฌ ํ๋ ์์ ์ฌ์ฌ์ฉํด ์ ํ ๋ช ๋ น์ผ๋ก ๋ณํํ๋ ์ต์ ํ์ ๋๋ค. ํต์ฌ์ โ๋ง์ง๋ง ๋์โ์ด๋ผ๋ ์ โ
return Func(...)์ฒ๋ผ ํธ์ถ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋๋ก ๋ฐํํ๋ฉด ํธ์ถ ํ ํ ์ผ์ด ์์ด ํ์ฌ ํ๋ ์์ ๋ฒ๋ ค๋ ๋ฉ๋๋ค. ๋ฐ๋๋กreturn n * Func(...)์ฒ๋ผ ํธ์ถ ํ ๊ณฑ์ ์ด ๋ ์์ผ๋ฉด ๊ณฑ์ ์ ์ํด ํ์ฌ ํ๋ ์์ด ์ด์์์ด์ผ ํด์ TCO ๋ถ๊ฐ์ ๋๋ค.C++์์ ํ์ค์ด TCO๋ฅผ ๋ณด์ฅํ์ง ์์ต๋๋ค. GCC/Clang์
-O2/-O3์ต์ ํ์์ ์ผ๋ถ ์ผ์ด์ค๋ง ์ ์ฉํ๊ณ , MSVC๋ ๋ ๋ณด์์ ์ ๋๋ค. ๋๋ฒ๊ทธ ๋น๋์์ ๊ฑฐ์ ์ ์ฉ ์ ๋ฉ๋๋ค. ๊ทธ๋์ TCO์ ์์กดํ ๊น์ ์ฌ๊ท ์ฝ๋๋ C++์์ ์ ๋ขฐํ ์ ์๋ ํจํด์ด๊ณ , ์์ ์ ์ํ๋ฉด ๋ฐ๋ณต๋ฌธ์ด๋ ๋ช ์์ ์คํ์ผ๋ก ๋ฐ๊ฟ์ผ ํฉ๋๋ค. Scheme/Haskell ๊ฐ์ ํจ์ํ ์ธ์ด๋ TCO๋ฅผ ํ์ค์ผ๋ก ๋ณด์ฅํ๋ ์ด ๋ถ๋ถ์ด ๋ค๋ฆ ๋๋ค.
Q5. โnaive ํผ๋ณด๋์น๊ฐ ์ ๊ทธ๋ ๊ฒ ๋๋ฆฐ๊ฐ์?โ
๊ฐ์ ๋ถ๋ถ ๋ฌธ์ ๋ฅผ ๋ฐ๋ณต ๊ณ์ฐํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
fib(n) = fib(n-1) + fib(n-2)๋ก ์ ์ํ๋ฉดfib(40)์ ๊ตฌํ๊ธฐ ์ํดfib(39)ํ ๋ฒ,fib(38)์ ๋ ๋ฒ(fib(40)์์ ํ ๋ฒ +fib(39)์์ ํ ๋ฒ)โฆ ์ด๋ฐ ์์ผ๋ก ๊ฐ์ ๊ฐ์ ์ง์์ ์ผ๋ก ๋ง์ด ๋ค์ ๊ณ์ฐํฉ๋๋ค. ํธ์ถ ํธ๋ฆฌ์ ํฌ๊ธฐ๊ฐ O(2^n) ์ด๊ณfib(40)์ด๋ฉด ์ฝ 10์ต ๋ฒ ํธ์ถ์ ๋๋ค.๊น์ด ์์ฒด๋ n์ด๋ผ ์คํ ํ๊ณ๋ ์ ๋์ง๋ง(๋ฉ์ธ 1MB๋ ์ถฉ๋ถ), ์๊ฐ์ด ํญ๋ฐํฉ๋๋ค. ๋ฉ๋ชจ์ด์ ์ด์ ์ผ๋ก ๊ฐ์ ๊ฐ์ ์บ์ฑํ๋ฉด ํธ์ถ ํธ๋ฆฌ๊ฐ ํํํด์ ธ O(n)์ด ๋ฉ๋๋ค. DP(๋ฐ๋ณต๋ฌธ)๋ก ํ๋ฉด ์๊ฐ O(n), ๊ณต๊ฐ O(1), ์คํ ํ ํ๋ ์์ผ๋ก ๋๋ฉ๋๋ค. ์ด๊ฒ โ์ฌ๊ท + ์ค๋ณต ๋ถ๋ถ ๋ฌธ์ = ์ํ ์ ํธโ์ ๋ํ ์ฌ๋ก์ ๋๋ค.
Q6. โ์คํ ์ค๋ฒํ๋ก์ ๋ฒํผ ์ค๋ฒํ๋ก์ ์ฐจ์ด๋?โ
๋ ๋ค โ๋ฉ๋ชจ๋ฆฌ ์์ญ ํ๊ณ๋ฅผ ๋์๋คโ๋ ์ ์ ๊ฐ์ง๋ง ์์ญ๊ณผ ๊ฒฐ๊ณผ๊ฐ ๋ค๋ฆ ๋๋ค.
Stack Overflow๋ ์คํ ์์ญ ์์ฒด๊ฐ ํ๊ณ ๋๋ฌํ ๊ฒฝ์ฐ๋ก, OS๊ฐ ๊ฐ๋ ํ์ด์ง์์ ์ก์ ์ฆ์ ์์ธ๋ฅผ ๋ฐ์์ํต๋๋ค. ๋ณดํต ์ ์งํ ํฌ๋์๋ก ๋๋์ง ๋ณด์ ๋ฌธ์ ๋ ์ ์ ๋ฉ๋๋ค. ์์ธ์ ๋ฌดํ ์ฌ๊ทยท๊น์ ์ฌ๊ทยท๊ฑฐ๋ ์ง์ญ ๋ณ์์ ๋๋ค.
Buffer Overflow๋ ์คํ ์์ ์๋ ํ ๋ฒํผ(์:
char buf[10])์ ๊ทธ ํฌ๊ธฐ๋ฅผ ๋๋ ๋ฐ์ดํฐ๋ฅผ ์ฐ๋ ๊ฒฝ์ฐ์ ๋๋ค. ์คํ ์์ญ ์์ฒด๋ ์ ๋์ง๋ง, ๊ทธ ๋ฒํผ ์์ชฝ์ ๋ค๋ฅธ ๋ฐ์ดํฐ(์ด์ ํ๋ ์์ ๋ฆฌํด ์ฃผ์๋ ์ง์ญ ๋ณ์)๋ฅผ ๋ฎ์ด์๋๋ค. ์ด๊ฒ ๊ณ ์ ์ ๋ณด์ ๊ณต๊ฒฉ ๋ฒกํฐ์ ๋๋ค โ ๊ณต๊ฒฉ์๊ฐ ๋ฆฌํด ์ฃผ์๋ฅผ ์๊ธฐ ์ฝ๋ ์ฃผ์๋ก ๋ฎ์ด์ฐ๋ฉด ํจ์๊ฐ ๋ฆฌํดํ๋ฉด์ ๊ณต๊ฒฉ์ ์ฝ๋๋ฅผ ์คํํฉ๋๋ค(์คํ ์ค๋งค์ฑ). ๊ทธ๋์ ํ๋ OS/์ปดํ์ผ๋ฌ๋ stack canary, ASLR, NX bit ๊ฐ์ ๋ฐฉ์ด๋ฅผ ๋ก๋๋ค.ํ ์ค ์์ฝ: ์คํ ์ค๋ฒํ๋ก = ์์ญ ํ๊ณ ๋๋ฌ(์ฆ์ ์์ธ), ๋ฒํผ ์ค๋ฒํ๋ก = ์์ญ ์ ํ ๋ณ์ ํ๊ณ ๋๋ฌ(๋ณด์ ์ํ).
Q7. โ์คํ ๊ฐ๋ ํ์ด์ง(guard page)๊ฐ ๋ญ๊ฐ์?โ
OS๊ฐ ์คํ ์์ญ ๋์ ๊น์๋๋ ๋ณดํธ์ฉ ํ์ด์ง์ ๋๋ค. ์ด ํ์ด์ง์๋ OS๊ฐ ํน๋ณ ํ์๋ฅผ ํด๋์ด ์ ๊ทผํ๋ฉด ์ฆ์ ํ์ด์ง ํดํธ๊ฐ ๋๋๋ก ๋ง๋ค์ด ๋ก๋๋ค. ์คํ์ด ์๋ผ๋ค๊ฐ ๊ฐ๋ ํ์ด์ง์ ๋ฟ์ผ๋ฉด ํ์ด์ง ํดํธ โ OS ์์ธ ํธ๋ค๋ฌ๋ก ์ ํ โ STATUS_STACK_OVERFLOW(Windows) ๋๋ SIGSEGV(Linux) ๋ณํ๋ฉ๋๋ค.
๊ฐ๋ ํ์ด์ง์ ์ญํ ์ด ๋ ๊ฐ์ง์ ๋๋ค. ์ฒซ์งธ ๋น ๋ฅธ ๊ฒ์ถ โ ํ๊ณ ๋๋ฌ์ ์ ํํ ์์ ์ ์ก์ต๋๋ค. ๊ฐ๋ ํ์ด์ง๊ฐ ์์ผ๋ฉด ์คํ์ด ๋ค๋ฅธ ๋ฉ๋ชจ๋ฆฌ(ํยท๋ค๋ฅธ ๋งคํ)๋ฅผ ์นจ๋ฒํ๊ณ ๋์์ผ ๋ฐ๊ฒฌ๋์ด ๋๋ฒ๊น ์ด ์ด๋ ต์ต๋๋ค. ๋์งธ ๋ค๋ฅธ ์์ญ ๋ณดํธ โ ํ๊ณ ๋๋จธ์ ๋ฉ๋ชจ๋ฆฌ์ ์ํฅ์ ์ฃผ๊ธฐ ์ ์ ์ฐจ๋จํฉ๋๋ค.
Windows๋ ๊ฐ๋ ํ์ด์ง๋ฅผ ๋ง๋ ๋ค์ ํ ๋ฒ ๋ commit์ผ๋ก ํ์ฅ(๋ฏธ๋ฆฌ reserve๋ ๋ฒ์ ์์์)ํ๋ ์ ์ฑ ๋ ์ฐ๊ณ , ๊ทธ ํ๊ณ๊น์ง ๋ค ์ฑ์ฐ๋ฉด STATUS_STACK_OVERFLOW๋ฅผ ๋์ง๋๋ค. Linux๋ ๋น์ทํ๊ฒ ๊ฐ๋ ์์ญ์ ๋๊ณ ํ๊ณ๋ฅผ ๊ฐ์ ํฉ๋๋ค.
Q8. โ์ธ๋ฆฌ์ผ์์ ์คํ ํฌ๊ธฐ๋ฅผ ๋๋ ค์ผ ํ ๋๊ฐ ์๋์?โ
ํํ์ง ์์ง๋ง ๋ถ๋ช ํ ์์ต๋๋ค. ์์ปค ์ค๋ ๋์์ ๊น์ ํธ๋ฆฌ/๊ทธ๋ํ ์๊ณ ๋ฆฌ์ฆ์ ๋๋ฆด ๋, ๋๋ ๊ฑฐ๋ํ ์๋ฆฌ์ผ๋ผ์ด์ฆ ์์ (์ ์ฅ ์์คํ , ์ง๋ ฌํ๊ธฐ)์ ์์ปค์์ ์ฒ๋ฆฌํ ๋์ ๋๋ค. ์ด๋ฐ ๊ฒฝ์ฐ
FRunnableThread::Create์InStackSize์ธ์๋ฅผ ๋ช ์ํด 8MB๋ 16MB๋ก ํค์๋๋ค.๊ฒ์ ์ค๋ ๋ ์คํ ํฌ๊ธฐ๋ ์์ง์ด ์ก๊ณ ์ฌ์ฉ์๊ฐ ์ง์ ๋ฐ๊พธ๊ธฐ ์ด๋ ค์ฐ๋, ๊ฒ์ ์ค๋ ๋์์ ์๊ณ ๋ฆฌ์ฆ์ ๋ฐ๋ณต๋ฌธ/๋ช ์์ ์คํ์ผ๋ก ๋ฐ๊พธ๋ ๊ฒ ์ ๊ณต๋ฒ์ ๋๋ค. Tick() ์์์ ๊น์ ์ฌ๊ท๋ฅผ ๋ง๋๋ ํจํด์ ์ปจ๋ฒค์ ์ ๊ธ์ง์ ๋๋ค. BehaviorTree๋ ๊น์ด๋ฅผ ๋ถํ (์๋ธํธ๋ฆฌ BTSubtree)๋ก ๊ด๋ฆฌํด ํ ํ๊ฐ ํจ์ค์ ๊น์ด๋ฅผ ์ค์ ๋๋ค.
์ ๋ฆฌํ๋ฉด ์คํ ํฌ๊ธฐ ๋๋ฆฌ๊ธฐ๋ ์์ปค ์ค๋ ๋์ ํ์ ํด์ ์๊ธ์กฐ์น๋ก ์ฐ๊ณ , ๊ฒ์ ์ค๋ ๋์ ์ผ๋ฐ ์ฝ๋๋ ์๊ณ ๋ฆฌ์ฆ ์์ค์์ ์ฌ๊ท ๊น์ด๋ฅผ ์ค์ด๋ ์ชฝ์ด ์์ ํฉ๋๋ค.
Q9. โ์ฌ๊ท ๊น์ด๋ฅผ OS๊ฐ ๊ฐ์ ๋ก ์ ํํ๋์?โ
์ง์ ์ ์ผ๋ก โ์ฌ๊ท ๊น์ดโ๋ผ๋ ๊ฐ๋ ์ผ๋ก ์ ํํ์ง ์์ต๋๋ค. OS๋ ์คํ ์์ญ ํฌ๊ธฐ๋ง ๊ฐ์ ํ๊ณ , ์ฌ๊ท ๊น์ด๋ ๊ทธ ์์์ ์์ฐ์ค๋ฝ๊ฒ ํ๊ณ๊ฐ ๊ฒฐ์ ๋ฉ๋๋ค. ํ ํ๋ ์์ด ํ๊ท 100๋ฐ์ดํธ๋ฉด 1MB ์คํ์ ์ฝ 1๋ง ๊น์ด๊น์ง, ํ ํ๋ ์์ด 1KB๋ฉด 1MB ์คํ์ 1000 ๊น์ด๊น์ง ๊ฐ๋ฅ โ ํ๋ ์ ํฌ๊ธฐ์ ์คํ ํฌ๊ธฐ์ ๋น์จ๋ก ์ ํด์ง๋๋ค.
์ผ๋ถ ์ธ์ด ๋ฐํ์์ ์์ฒด์ ์ผ๋ก ๊น์ด ์นด์ดํฐ๋ฅผ ๋ก๋๋ค. Python์
sys.setrecursionlimit()๊ธฐ๋ณธ๊ฐ 1000์ผ๋ก ํ๋ ์ฝ๋ฉ๋ ํ๊ณ๋ฅผ ๋์ด RecursionError๋ฅผ ๋ฏธ๋ฆฌ ๋์ง๋๋ค(์คํ ์ค๋ฒํ๋ก๋ณด๋ค ์์ ํ ์ข ๋ฃ๋ฅผ ์ํด). JVM์ ์ค๋ ๋ ์คํ ํฌ๊ธฐ(-Xss) ํ๊ณ๊น์ง ๊ฐ์ StackOverflowError๋ฅผ ๋์ง๋๋ค. C++์ ๋ณ๋ ์นด์ดํฐ ์์ด OS ์คํ ํ๊ณ๋ง ์ ์ฉ๋ฉ๋๋ค.
Q10. โJVM์ด๋ Python์ฒ๋ผ ์คํ ์ฌ์ด์ฆ๊ฐ ๋ค๋ฅธ ์ธ์ด๋?โ
์ธ์ด๋ง๋ค ์ ์ฑ ๊ณผ ํ๊ณ๊ฐ ๋ค๋ฆ ๋๋ค.
JVM โ
-XssJVM ์ต์ ์ผ๋ก ์ค๋ ๋๋ณ ์คํ ํฌ๊ธฐ ์ง์ . ๊ธฐ๋ณธ 512KB~1MB(JVM ๊ตฌํ/ํ๋ซํผ๋ณ). ํ๊ณ ๋๋ฌ ์StackOverflowError์์ธ(์๋ฌ์ง๋ง catch ๊ฐ๋ฅ, ๋จ ๊ถ์ฅ ์ ํจ). HotSpot JVM์ ์ธํฐํ๋ฆฌํฐ ๋ชจ๋์์ ํ ํ๋ ์๋น ์ค๋ฒํค๋๊ฐ ํฌ๋ ๊ฐ์ ๊น์ด๋ผ๋ C++๋ณด๋ค ์ผ์ฐ ํฐ์ง ์ ์์ต๋๋ค.Python (CPython) โ
sys.setrecursionlimit()๋ก ๋ช ์์ ๊น์ด ์นด์ดํฐ. ๊ธฐ๋ณธ 1000์ผ๋ก ๋งค์ฐ ๋ณด์์ . ์ด์ ๋ CPython ์ธํฐํ๋ฆฌํฐ ์์ฒด๊ฐ C ์คํ์ ๊น๊ฒ ์ฐ๊ธฐ ๋๋ฌธ โ Python ๊น์ด 1000์ด C ์คํ์ผ๋ก ์ KBร1000 = ์ MB๋ก ์ด๋ฏธ ์ํ ์์.sys.setrecursionlimit(10000)์ฒ๋ผ ๋๋ฆด ์ ์์ง๋ง ์ค์ OS ์คํ ํ๊ณ๊น์ง๋ง ์๋ฏธ ์๊ณ ๊ทธ ์ด์์ segfault.Go โ ๊ณ ๋ฃจํด์ ์ธ๊ทธ๋จผํธ ์คํ(์์ ) / ๋ถํ ์คํ(ํ์ฌ) ์ผ๋ก ์์ ์ ์๊ฒ(8KB) ์ก๊ณ ํ์ํ ๋ ์๋ ํ์ฅ. ๊ทธ๋์ ์๋ง ๊ฐ ๊ณ ๋ฃจํด์ ๋์๋ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ ํฐ์ง๋๋ค. C++
std::thread(1:1, ๊ณ ์ 1~8MB)์ ๊ฒฐ์ ์ ์ธ ์ฐจ์ด.Rust โ C++๊ณผ ๊ฐ์ด OS ์คํ ์ฌ์ฉ. ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ช ์์ ๊น์ด ๋ณดํธ๋ ์์. ๋จ ์ปดํ์ผ๋ฌ๊ฐ stack overflow ๊ฒ์ฌ๋ฅผ ๋ ์๊ฒฉํ ํ๋ ์ต์ ์ ๊ณต.
Erlang/Elixir โ BEAM VM์ด ์์ฒด ์คํ์ ํ ์์ ๋๊ณ ๋์ ํ์ฅ. ์ฌ์ค์ ๊น์ด ํ๊ณ ์์(๊ฐ์ฉ ํ ๋ฉ๋ชจ๋ฆฌ๋งํผ). ์ธ์ด ์ฐจ์์์ ์ฌ๊ท๋ฅผ ๊ถ์ฅํ๋ ์ด์ .
ํ ์ค: C++/Java/Python์ OS ์ค๋ ๋ ์คํ์ ์์กด(๊ณ ์ ํฌ๊ธฐ), Go/Erlang์ ๊ฐ๋ณ ์คํ์ผ๋ก ๊น์ด ํ๊ณ ํํผ. ์ด ์ฐจ์ด๊ฐ ๋์์ฑ ๋ชจ๋ธ ์ฐจ์ด์ ํ ์ถ์ ๋๋ค(Go๊ฐ ์๋ง ๊ณ ๋ฃจํด์ ์ฝ๊ฒ ๋์ธ ์ ์๋ ์ด์ ).
13. ํต์ฌ ์์ฝ ์นด๋ (์ฌ๊ฒ์ฌ)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Stack Overflow = ์ค๋ ๋ ์คํ ์์ญ(๊ณ ์ ํฌ๊ธฐ)์ด ํ๊ณ๋ฅผ ๋์ด ๋ ํ๋ ์์ ๋ชป ์๋ ์ํ.
ํจ์ ํธ์ถ๋ง๋ค SP ๊ฐ์ โ ๊ฐ๋ ํ์ด์ง ๋ฟ์ผ๋ฉด OS ์์ธ.
๋ฐ์ ์์ธ 4๊ฐ์ง:
โ ๋ฌดํ ์ฌ๊ท โ base case ๋๋ฝ
โก ๋๋ฌด ๊น์ ์ฌ๊ท โ naive ํผ๋ณด๋์น (O(2^n)), ๊น์ ํธ๋ฆฌ DFS
โข ๊ฑฐ๋ํ ์ง์ญ ๋ณ์ โ int arr[1000000] (4MB) > ๋ฉ์ธ ์คํ (1MB on Windows)
โฃ ๋ฌดํ ์ํธ ํธ์ถ โ AโBโAโB...
ํ๋ซํผ๋ณ ์คํ ํฌ๊ธฐ (๊ธฐ๋ณธ):
Windows ๋ฉ์ธ 1MB (/STACK:reserve,commit ๋ง์ปค ์ต์
)
Linux ๋ฉ์ธ 8MB (ulimit -s, setrlimit RLIMIT_STACK)
์์ปค 1~2MB (pthread_attr_setstacksize)
์ธ๋ฆฌ์ผ OS ๊ธฐ๋ณธ (FRunnableThread::Create์ InStackSize ์ธ์๋ก ๋ช
์)
ํด๊ฒฐ 5๊ฐ์ง:
โ ์ข
๋ฃ ์กฐ๊ฑด ๊ฒ์ฆ โ base case + ์ธ์ ๋จ์กฐ ๊ฐ์
โก ์ฌ๊ท โ ๋ฐ๋ณต๋ฌธ ๋ณํ โ for/while, ์คํ ํ ํ๋ ์๋ง ์ฌ์ฉ
โข ๋ฉ๋ชจ์ด์ ์ด์
/ DP โ naive ํผ๋ณด๋์น O(2^n) โ O(n)
โฃ TCO (Tail Call) โ C++ ํ์ค ๋ฏธ๋ณด์ฅ, ๋๋ฒ๊ทธ ๋น๋ ์ํ
โค ๋ช
์์ ์คํ ์๋ฃ๊ตฌ์กฐ โ std::stack/std::vector๋ก ํธ์ถ ์คํ์ ํ์ ์๋ฎฌ๋ ์ด์
ํฐ ๋ฐ์ดํฐ๋ ์คํ โ ํ (03๋ฒ ํ๊ท):
int arr[1000000]
โ std::vector<int>(1000000)
โ std::unique_ptr<int[]>::make_unique
โ static (Data/BSS ์์ญ)
์ง๋จ:
Windows: STATUS_STACK_OVERFLOW (0xC00000FD) โ SEH ์์ธ
Linux: SIGSEGV โ ๊ฐ๋ ํ์ด์ง ์ ๊ทผ
์ฝ์คํ ๋์ผ ํจ์ ๋ฐ๋ณต (์ฌ๊ท) / ๋ ํจ์ ๋ฒ๊ฐ์ (์ํธ ํธ์ถ) / ์งง์ (๊ฑฐ๋ ๋ณ์)
๊ฐ๋ ํ์ด์ง (Guard Page):
์คํ ๋์ OS๊ฐ ๊น์๋ ๋ณดํธ ํ์ด์ง. ์ ๊ทผ ์ ์ฆ์ ํ์ด์ง ํดํธ โ ์์ธ.
์ญํ : โ ๋น ๋ฅธ ๊ฒ์ถ โก ๋ค๋ฅธ ๋ฉ๋ชจ๋ฆฌ ์์ญ ๋ณดํธ.
์ธ๋ฆฌ์ผ:
FRunnableThread::Create(runnable, name, InStackSize, priority) โ ๋ช
์
BehaviorTree ๊น์ด ๋ถํ (BTSubtree)
Tick() ์ ๊น์ ์ฌ๊ท ๊ธ์ง โ ๋ช
์์ ์คํ/BFS/์์ปค ๋ถ๋ฆฌ
Blueprint ๋ฌดํ ํจ์ ํธ์ถ โ ์๋ํฐ ํฌ๋์ (๊ฐ์ ๋ฉ์ปค๋์ฆ)
์ธ์ด๋ณ ์ ์ฑ
:
C++ โ OS ์คํ ํ๊ณ๋ง (๋ณ๋ ์นด์ดํฐ ์์)
Java โ -Xss + StackOverflowError
Python โ sys.setrecursionlimit (๊ธฐ๋ณธ 1000)
Go โ ๋ถํ ์คํ (์๋ ํ์ฅ, ์ฌ์ค์ ํ๊ณ ์์)
Erlang โ VM ์์ฒด ๊ฐ๋ณ ์คํ
๊ธฐ์ตํ ํ ์ค:
๊น์ด๊ฐ ์
๋ ฅ ํฌ๊ธฐ์ ๋น๋กํ๋ ์ฌ๊ท๋ ์ํ ์ ํธ. ๋ฐ๋ณต๋ฌธ/๋ช
์์ ์คํ์ผ๋ก ๋ฐ๊พธ์.
14. ํ๊ท ๋ค๋ฆฌ โ ๋ค๋ฅธ CS ํ์ผ ์ฐ๊ฒฐ
| ํ์ผ | ์ฐ๊ฒฐ ์ง์ |
|---|---|
| 01_runtime | ๋ฉ๋ชจ๋ฆฌ 4์์ญ(Code/Data/Heap/Stack) โ Stack ์์ญ์ ํ๊ณ๊ฐ ๊ณง ์คํ ์ค๋ฒํ๋ก์ ๊ทผ์. SPยทํ๋ ์ ๊ฐ๋ ์ ์ถ๋ฐ์ |
| 03_new_vs_malloc | ํฐ ๋ฐ์ดํฐ๋ฅผ ์คํ ๋์ ํ์ผ๋ก ์ฎ๊ธฐ๋ ๊ฒ ํต์ฌ ํด๊ฒฐ์ฑ
. std::vector, std::unique_ptr<T[]>, make_unique๊ฐ ์ง์ ๋ฑ์ฅ |
| 09_rtti_raii | std::unique_ptr / std::vector ๋ฑ RAII๋ก ํ ์์์ ์๋ ๊ด๋ฆฌ โ ์คํโํ ์ด์ ์ด ์์ ํ ์ด์ |
| 11_smart_pointer | ๊ฑฐ๋ ๋ฐ์ดํฐ ํ ์ด์ ์ ์ค๋งํธ ํฌ์ธํฐ๋ก RAII ํ์ฉ โ ๋์ยท๋๊ธ๋ง ๋์ ๋ฐฉ์ง |
| 13_vector_vs_list | std::vector๊ฐ ๋ฐ์ดํฐ๋ฅผ ํ ์ฐ์ ๋ฉ๋ชจ๋ฆฌ์ ๋๋ ์ โ ์คํ ๊ฑฐ๋ ๋ฐฐ์ด์ ์์ฐ์ค๋ฌ์ด ๋์ฒด |
| 16_stl_containers | std::stack์ ๋ด๋ถ์ ์ผ๋ก std::deque(๋๋ ๋ค๋ฅธ ์ปจํ
์ด๋) โ ๋ช
์์ ์คํ ๋ณํ ์ ์ฌ์ฉ. ์ปจํ
์ด๋ ์ด๋ํฐ ๊ฐ๋
|
| 19_process_vs_thread | ์ค๋ ๋๋ง๋ค ์๊ธฐ ์คํ์ ๊ฐ์ง๋ค๋ ์ฌ์ค(Q14ยทQ15์์ ์งง๊ฒ ๋ค๋ฃธ) โ 20๋ฒ์์ ๋ณธ ์ฃผ์ ๋ก ํ์ฅ. FRunnable/FRunnableThread์ ์คํ ํฌ๊ธฐ ์ธ์๊ฐ ์ง์ ๋ฑ์ฅ |