ํฌ์ŠคํŠธ

CS โ€” stack overflow

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_OVERFLOWWindows 0xC00000FD. SEH ์˜ˆ์™ธ
ย SIGSEGVLinux. ์‹œ๊ทธ๋„ 11. ๊ฐ€๋“œ ํŽ˜์ด์ง€ ์ ‘๊ทผ ์‹œ ๋ฐœ์ƒ
ย ์ฝœ์Šคํƒ ๋ถ„์„๋””๋ฒ„๊ฑฐ๋กœ ๋™์ผ ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜๋ณต ๋“ฑ์žฅํ•˜๋ฉด ์žฌ๊ท€ ํŒจํ„ด ์ฆ‰์‹œ ์‹๋ณ„
์–ธ์–ด/์—”์ง„C++ ํ‘œ์ค€์Šคํƒ ํฌ๊ธฐยทTCO ๋ชจ๋‘ ํ‘œ์ค€ ๋ฏธ๋ณด์žฅ โ€” ๊ตฌํ˜„์ฒด ์˜์กด
ย JVM-Xss ์˜ต์…˜์œผ๋กœ ์Šค๋ ˆ๋“œ ์Šคํƒ ํฌ๊ธฐ ์ง€์ •. StackOverflowError ์˜ˆ์™ธ
ย Pythonsys.setrecursionlimit(). ๊ธฐ๋ณธ 1000. ์ธํ„ฐํ”„๋ฆฌํ„ฐ ์Šคํƒ ํ•œ๊ณ„
ย ์–ธ๋ฆฌ์–ผ FRunnableFRunnableThread::Create์˜ InStackSize ์ธ์ž๋กœ ๋ช…์‹œ
ย ์–ธ๋ฆฌ์–ผ BehaviorTree๊นŠ์ด ์ œํ•œ ์ปจ๋ฒค์…˜. ๋„ˆ๋ฌด ๊นŠ์€ ํŠธ๋ฆฌ๋Š” ๋ถ„ํ• 

๋ชฉ์ฐจ

  1. ํ•ต์‹ฌ ์š”์•ฝ ์นด๋“œ
  2. ํ•œ ์ค„ ์ •์˜ โ€” Stack Overflow๋ž€ ๋ฌด์—‡์ธ๊ฐ€
  3. ์Šคํƒ ๋ฉ”๋ชจ๋ฆฌ ๊ตฌ์กฐ โ€” ์™œ ํ•œ๊ณ„๊ฐ€ ์žˆ๋Š”๊ฐ€ (01๋ฒˆ ํšŒ๊ท€)
  4. ๋ฐœ์ƒ ์›์ธ 4๊ฐ€์ง€
  5. ํ”Œ๋žซํผ๋ณ„ ์Šคํƒ ํฌ๊ธฐ โ€” Windows / Linux / ์›Œ์ปค / ์–ธ๋ฆฌ์–ผ
  6. ์Šคํƒ vs ํž™ โ€” ํฐ ๋ฐ์ดํ„ฐ๋ฅผ ํž™์œผ๋กœ ์˜ฎ๊ธฐ๊ธฐ (03๋ฒˆ ํšŒ๊ท€)
  7. ํ•ด๊ฒฐ์ฑ… 5๊ฐ€์ง€
  8. ์ปดํŒŒ์ผ๋ŸฌยทOS ์ฐจ์› โ€” ๊ฐ€๋“œ ํŽ˜์ด์ง€์™€ ์Šคํƒ ํฌ๊ธฐ ์กฐ์ •
  9. C++ ์ฝ”๋“œ ์˜ˆ์‹œ โ€” ํ”ผ๋ณด๋‚˜์น˜ / ๊ฑฐ๋Œ€ ๋ฐฐ์—ด / ๋ช…์‹œ์  ์Šคํƒ
  10. ์–ธ๋ฆฌ์–ผ์—์„œ์˜ ์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ
  11. ๋””๋ฒ„๊น… โ€” ์Šคํƒ ํŠธ๋ ˆ์ด์Šค๋กœ ์žฌ๊ท€ ํŒจํ„ด ์‹๋ณ„
  12. ๊ผฌ๋ฆฌ์งˆ๋ฌธ ์˜ˆ์ƒ ๊ฒฝ๋กœ
  13. ํ•ต์‹ฌ ์š”์•ฝ ์นด๋“œ (์žฌ๊ฒŒ์žฌ)
  14. ํšŒ๊ท€ ๋‹ค๋ฆฌ โ€” ๋‹ค๋ฅธ 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๊ฐ€์ง€ ํŠน์ง•

  1. LIFO ์ž๋™ ๊ด€๋ฆฌ โ€” ํ•จ์ˆ˜ ์ง„์ž… ์‹œ push, ๋ฆฌํ„ด ์‹œ pop. ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ prolog/epilog ์ฝ”๋“œ๋กœ ์ž๋™ ์ƒ์„ฑ. ๋ช…์‹œ์  delete ๋ถˆํ•„์š”.
  2. ๊ณ ์ • ํฌ๊ธฐ โ€” ์Šค๋ ˆ๋“œ ์ƒ์„ฑ ์‹œ OS๊ฐ€ ํ•œ ๋ฒˆ์— ์žก๊ณ  ๋ณดํ†ต ํ™•์žฅ ์•ˆ ๋จ. (ํ™•์žฅ ๊ฐ€๋Šฅํ•œ OS๋„ ์žˆ์ง€๋งŒ ํ•œ๊ณ„๊ฐ€ ์žˆ์Œ)
  3. ๋น ๋ฆ„ โ€” SP ๊ฐ์†Œ ํ•œ ๋ฒˆ์ด๋ฉด ๋. ์บ์‹œ ์นœํ™”์ (์—ฐ์† ๋ฉ”๋ชจ๋ฆฌ). ํž™ ํ• ๋‹น๋ณด๋‹ค 100๋ฐฐ ์ด์ƒ ๋น ๋ฅธ ๊ฒฝ์šฐ๋„.
  4. ์Šค๋ ˆ๋“œ๋ณ„ ๋…๋ฆฝ โ€” 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 / ์›Œ์ปค / ์–ธ๋ฆฌ์–ผ

๊ธฐ๋ณธ ์Šคํƒ ํฌ๊ธฐ (๋ฉ”์ธ ์Šค๋ ˆ๋“œ)

ํ”Œ๋žซํผ๊ธฐ๋ณธ ํฌ๊ธฐ๋ณ€๊ฒฝ ๋ฐฉ๋ฒ•
Windows1MB๋ง์ปค ์˜ต์…˜ /STACK:reserve,commit
Linux8MB์…ธ ulimit -s [KB], ์ฝ”๋“œ setrlimit(RLIMIT_STACK, ...)
macOS8MB (๋ฉ”์ธ) / 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 Overflowbad_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 โ€” -Xss JVM ์˜ต์…˜์œผ๋กœ ์Šค๋ ˆ๋“œ๋ณ„ ์Šคํƒ ํฌ๊ธฐ ์ง€์ •. ๊ธฐ๋ณธ 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_raiistd::unique_ptr / std::vector ๋“ฑ RAII๋กœ ํž™ ์ž์›์„ ์ž๋™ ๊ด€๋ฆฌ โ€” ์Šคํƒโ†’ํž™ ์ด์ „์ด ์•ˆ์ „ํ•œ ์ด์œ 
11_smart_pointer๊ฑฐ๋Œ€ ๋ฐ์ดํ„ฐ ํž™ ์ด์ „ ์‹œ ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ๋กœ RAII ํ™œ์šฉ โ€” ๋ˆ„์ˆ˜ยท๋Œ•๊ธ€๋ง ๋™์‹œ ๋ฐฉ์ง€
13_vector_vs_liststd::vector๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ํž™ ์—ฐ์† ๋ฉ”๋ชจ๋ฆฌ์— ๋‘๋Š” ์  โ€” ์Šคํƒ ๊ฑฐ๋Œ€ ๋ฐฐ์—ด์˜ ์ž์—ฐ์Šค๋Ÿฌ์šด ๋Œ€์ฒด
16_stl_containersstd::stack์€ ๋‚ด๋ถ€์ ์œผ๋กœ std::deque(๋˜๋Š” ๋‹ค๋ฅธ ์ปจํ…Œ์ด๋„ˆ) โ€” ๋ช…์‹œ์  ์Šคํƒ ๋ณ€ํ™˜ ์‹œ ์‚ฌ์šฉ. ์ปจํ…Œ์ด๋„ˆ ์–ด๋Œ‘ํ„ฐ ๊ฐœ๋…
19_process_vs_thread์Šค๋ ˆ๋“œ๋งˆ๋‹ค ์ž๊ธฐ ์Šคํƒ์„ ๊ฐ€์ง„๋‹ค๋Š” ์‚ฌ์‹ค(Q14ยทQ15์—์„œ ์งง๊ฒŒ ๋‹ค๋ฃธ) โ€” 20๋ฒˆ์—์„œ ๋ณธ ์ฃผ์ œ๋กœ ํ™•์žฅ. FRunnable/FRunnableThread์˜ ์Šคํƒ ํฌ๊ธฐ ์ธ์ž๊ฐ€ ์ง์ ‘ ๋“ฑ์žฅ
์ด ๊ธฐ์‚ฌ๋Š” ์ €์ž‘๊ถŒ์ž์˜ CC BY 4.0 ๋ผ์ด์„ผ์Šค๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

ยฉ GoldBoll. ์ผ๋ถ€ ๊ถŒ๋ฆฌ ๋ณด์œ 

Powered by Jekyll with Chirpy theme

์ธ๊ธฐ ํƒœ๊ทธ