CS β runtime
π 04/15 - Runtime (λ°νμ) μ 리
Notion μλ³Έ: https://www.notion.so/343f77b24d2f8146b9dfcf1c60ebd0cd λΆλͺ¨: μλ£ β Cs λ©΄μ μ€λΉ β 꼬리μ§λ¬Έ ν€μλ β Runtime
λͺ¨μλ©΄μ λ΅λ³ β βλ°νμμ΄λ 무μμΈκ°μ?β
λ°νμ(Runtime)μ νλ‘κ·Έλ¨μ΄ μ€νλκ³ μλ μκ°μ λ¨κ³λ₯Ό μλ―Έν©λλ€. μ»΄νμΌ νμμ΄ μμ€ μ½λλ₯Ό κΈ°κ³μ΄λ‘ λ³ννλ λ¨κ³λΌλ©΄, λ°νμμ κ·Έ κ²°κ³Όλ¬Όμ΄ μ€μ λ‘ OS μμμ λμνλ λ¨κ³μ
λλ€. λ°νμμλ λμ λ©λͺ¨λ¦¬ ν λΉκ³Ό ν΄μ , κ°μ ν¨μλ₯Ό ν΅ν λμ λμ€ν¨μΉ, RTTIλ₯Ό νμ©ν νμ
νλ³ λ±μ΄ μΌμ΄λ©λλ€. λ°νμ μλ¬λ μ»΄νμΌμ ν΅κ³Όνμ§λ§ μ€ν μ€μ λ°μνλ μ€λ₯λ‘, μΈκ·Έλ©ν
μ΄μ
ν΄νΈ, μ€ν μ€λ²νλ‘μ°, μ μλμ§ μμ λμ(UB) λ±μ΄ λνμ μ
λλ€. μΈλ¦¬μΌ μμ§μμλ BeginPlay(), Tick() κ°μ κ°μ ν¨μλ λ°νμμ vtableμ ν΅ν΄ λμ λμ€ν¨μΉλλ©°, IsA()λ Cast
ν€μλ μ 리
κΈ°λ³Έ κ°λ
- λ°νμ (Runtime) β νλ‘κ·Έλ¨μ΄ μ€ν μ€μΈ λ¨κ³; μ»΄νμΌ νμ μ΄ν OS μμμ λμνλ μκ°
- μ»΄νμΌ νμ (Compile Time) β μμ€ μ½λλ₯Ό κΈ°κ³μ΄λ‘ λ³ννλ λ¨κ³; νμ κ²μ¬Β·μ΅μ ν λ°μ
- λμ λ©λͺ¨λ¦¬ ν λΉ (Dynamic Memory Allocation) β λ°νμμ νμμ λ©λͺ¨λ¦¬λ₯Ό μμ² (
new/malloc) - RTTI (Runtime Type Information) β λ°νμμ κ°μ²΄μ μ€μ νμ μ μ‘°ννλ C++ λ©μ»€λμ¦
- λμ λμ€ν¨μΉ (Dynamic Dispatch) β vtableμ ν΅ν΄ λ°νμμ μ€μ ν¨μλ₯Ό κ²°μ Β·νΈμΆ
- μ μλμ§ μμ λμ (Undefined Behavior, UB) β νμ€μ΄ κ²°κ³Όλ₯Ό κ·μ νμ§ μλ μ½λ; λ°νμμ μμΈ‘ λΆκ°
ν€μλ λΆλ₯ν
- νμ κ²μ¬ β μ»΄νμΌ νμ (static_assert, ν νλ¦Ώ μΈμ€ν΄μ€ν)
- λμ λμ€ν¨μΉ β λ°νμ (virtual ν¨μ νΈμΆ, vtable μ°Έμ‘°)
- RTTI β λ°νμ (dynamic_cast, typeid)
- λ©λͺ¨λ¦¬ ν λΉ β λ°νμ (new/delete, malloc/free)
- λ°νμ μλ¬ β λ°νμ (segfault, μ€ν μ€λ²νλ‘μ°, UB)
μ»΄νμΌ νμ vs λ°νμ
μ»΄νμΌ νμμ μμ€ μ½λλ₯Ό κΈ°κ³μ΄λ‘ λ²μνλ λ¨κ³λ‘, λ¬Έλ² κ²μ¬Β·νμ κ²μ¬Β·μ΅μ νκ° μΌμ΄λ©λλ€. λ°νμμ μ»΄νμΌλ νλ‘κ·Έλ¨μ΄ OS μμμ μ€μ λ‘ μ€νλλ λ¨κ³λ‘, λ©λͺ¨λ¦¬ ν λΉΒ·λμ λμ€ν¨μΉΒ·I/O λ±μ΄ λ°μν©λλ€.
λΉκ΅:
- μμ : λΉλ μ / μ€ν μ
- μ£Όμ μμ : λ¬Έλ²Β·νμ κ²μ¬, μ΅μ ν, μ½λ μμ± / λ©λͺ¨λ¦¬ ν λΉ, λμ λμ€ν¨μΉ, I/O
- μλ¬ λ°κ²¬: μ»΄νμΌ μλ¬ (μ¦μ νΌλλ°±) / λ°νμ μλ¬ (μ€ν μ€ ν¬λμ)
- μ±λ₯ λΉμ©: λΉλ μκ°μ μλͺ¨ / μ€ν μ€ μλͺ¨ (μ§μ μν₯)
1
2
3
4
5
6
7
8
9
10
11
12
// ββ μ»΄νμΌ νμ ββββββββββββββββββββββββββββββββββββββββββ
static_assert(sizeof(int) == 4, "intλ 4λ°μ΄νΈμ¬μΌ ν¨");
constexpr int Square(int x) { return x * x; }
template<typename T> void Print(T val) { }
// ββ λ°νμ βββββββββββββββββββββββββββββββββββββββββββββββ
int n;
std::cin >> n; // λ°νμμ κ° κ²°μ
int* arr = new int[n]; // λ°νμ λ©λͺ¨λ¦¬ ν λΉ
Base* p = new Derived(); // λ°νμ κ°μ²΄ μμ±
p->VirtualFunc(); // λ°νμ λμ λμ€ν¨μΉ
delete[] arr; // λ°νμ λ©λͺ¨λ¦¬ ν΄μ
볡기:
- μ»΄νμΌ νμ λΉμ© = λΉλ μκ° μ¦κ° (μ€ν μ±λ₯μ 무κ΄)
- λ°νμ λΉμ© = μ€μ μ€ν μλμ μ§μ μν₯
constexpr/ ν νλ¦Ώ /static_assertβ μ»΄νμΌ νμμΌλ‘ λΉμ© μ΄λvirtual/new/dynamic_castβ λ°νμ λΉμ© λ°μ
RTTI (Runtime Type Information)
RTTIλ λ°νμμ κ°μ²΄μ μ€μ (λμ ) νμ
μ μ‘°νν μ μκ² ν΄μ£Όλ C++ λ©μ»€λμ¦μ
λλ€. dynamic_castμ typeid λ κ°μ§ λ°©λ²μΌλ‘ μ¬μ©νλ©°, κ°μ ν¨μκ° μλ ν΄λμ€(vtable 보μ )μμλ§ λμν©λλ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Animal { public: virtual ~Animal() {} };
class Dog : public Animal { public: void Bark() {} };
class Cat : public Animal {};
Animal* a = new Dog();
// 1. dynamic_cast β μμ ν λ€μ΄μΊμ€νΈ
Dog* d = dynamic_cast<Dog*>(a); // μ±κ³΅
if (d) d->Bark();
Cat* c = dynamic_cast<Cat*>(a); // μ€ν¨: nullptr λ°ν
// 2. typeid β νμ
μ 보 μ‘°ν
#include <typeinfo>
std::cout << typeid(*a).name();
if (typeid(*a) == typeid(Dog)) { /* Dogμμ νμΈ */ }
dynamic_cast vs static_cast:
- κ²μ¬ μμ : μ»΄νμΌ νμ / λ°νμ
- μμ μ±: νλ‘κ·Έλλ¨Έ μ± μ / μ€ν¨ μ nullptr (ν¬μΈν°) / μμΈ (μ°Έμ‘°)
- μ±λ₯: μ€λ²ν€λ μμ / vtable μ°Έμ‘°λ‘ λ°νμ λΉμ© λ°μ
- μ¬μ© 쑰건: κ°μ ν¨μ λΆνμ / κ°μ ν¨μ 1κ° μ΄μ νμ
볡기:
- RTTI =
dynamic_cast+typeidβ κ°μ ν¨μ μλ ν΄λμ€μμλ§ λμ dynamic_castμ€ν¨ μ ν¬μΈν°λ©΄nullptr, μ°Έμ‘°λ©΄std::bad_castμμΈ-fno-rttiμ»΄νμΌ μ΅μ μΌλ‘ RTTI λΉνμ±ν κ°λ₯- RTTI λ¨μ©μ μ€κ³ λ¬Έμ μ νΈ β κ°μ ν¨μλ‘ λ체 κ³ λ €
λ°νμ μλ¬ μ ν
λ°νμ μλ¬λ μ»΄νμΌμ μ±κ³΅νμ§λ§ μ€ν μ€μ νλ‘κ·Έλ¨μ΄ λΉμ μ μ’ λ£λκ±°λ μλͺ»λ κ²°κ³Όλ₯Ό λ΄λ μ€λ₯μ λλ€.
μ£Όμ μ ν:
- Segmentation Fault β μλͺ»λ λ©λͺ¨λ¦¬ μ κ·Ό (λ ν¬μΈν° μμ°Έμ‘°, ν΄μ λ λ©λͺ¨λ¦¬ μ κ·Ό)
- Stack Overflow β μ€ν λ©λͺ¨λ¦¬ μ΄κ³Ό (무ν μ¬κ·, κ³Όλν μ§μ λ³μ)
- Undefined Behavior (UB) β νμ€ λ―Έμ μ λμ (λΆνΈ μλ μ μ μ€λ²νλ‘μ°, λ²μ μ΄κ³Ό μ κ·Ό)
- λ©λͺ¨λ¦¬ λμ (Memory Leak) β ν λΉ ν ν΄μ λλ½ (new ν delete μμ)
- Double Free β κ°μ λ©λͺ¨λ¦¬ λ λ² ν΄μ
- std::exception β out_of_range, bad_alloc, bad_cast
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int* p = nullptr;
*p = 42; // nullptr μμ°Έμ‘° β segfault
void Infinite() { Infinite(); } // 무ν μ¬κ· β μ€ν μ€λ²νλ‘μ°
void Leak() {
int* x = new int(42);
// delete x; μμ β λ©λͺ¨λ¦¬ λμ
}
// μμ ν ν¨ν΄: RAII / μ€λ§νΈ ν¬μΈν°
void Safe() {
auto x = std::make_unique<int>(42);
}
볡기:
- λ°νμ μλ¬λ μ»΄νμΌλ¬κ° μ‘μ§ λͺ»ν¨ β μ€ν μ€ ν¬λμ
- UBλ ν¬λμ μμ΄ μ‘°μ©ν μλͺ»λ κ²°κ³Όλ₯Ό λΌ μ μμ΄ κ°μ₯ μν
- RAII / μ€λ§νΈ ν¬μΈν°λ‘ λ©λͺ¨λ¦¬ λμΒ·double free λ°©μ§
- AddressSanitizer, Valgrindλ‘ λ©λͺ¨λ¦¬ μ€λ₯ νμ§
λμ λ©λͺ¨λ¦¬ ν λΉ (ν vs μ€ν)
μ€νμ ν¨μ νΈμΆ μ μλμΌλ‘ ν λΉΒ·ν΄μ λλ λ©λͺ¨λ¦¬ μμμ΄κ³ , νμ λ°νμμ νλ‘κ·Έλλ¨Έκ° μ§μ new/deleteλ‘ κ΄λ¦¬νλ λ©λͺ¨λ¦¬ μμμ
λλ€.
ν vs μ€ν:
- ν λΉ μμ : ν¨μ μ§μ μ μλ / λ°νμ new/malloc νΈμΆ μ
- ν΄μ μμ : ν¨μ μ’ λ£ μ μλ / delete/free νΈμΆ μ (μλ)
- ν¬κΈ°: μ νμ (1~8MB) / κ°μ© RAM νλ λ΄
- μλ: λΉ λ¦ (SP λ μ§μ€ν° μ΄λ) / λλ¦Ό (OS μμ€ν μ½ κ°λ₯)
- μλͺ : μ€μ½ν λ΄ / λͺ μμ ν΄μ μ κΉμ§
1
2
3
4
5
6
7
void Example() {
int stackVar = 10; // μ€ν β μλ ν΄μ
int* heapVar = new int(20); // ν β μλ ν΄μ νμ
auto smart = std::make_unique<int>(30); // RAII
delete heapVar;
}
μΈλ¦¬μΌ μμ§κ³Ό λ°νμ
μΈλ¦¬μΌ μμ§μ λ°νμμ λ€μν λ©μ»€λμ¦μ μ¬μ©ν©λλ€. Cast<T>()λ RTTI κΈ°λ° μμ ν λ€μ΄μΊμ€νΈ, IsA<T>()λ νμ
κ²μ¬, κ°λΉμ§ 컬λ ν°(GC)κ° UObject ν λ©λͺ¨λ¦¬λ₯Ό λ°νμμ μλ κ΄λ¦¬ν©λλ€.
μ£Όμ κΈ°λ₯:
Cast<T>()β UObject νμ μμ λ€μ΄μΊμ€νΈ (dynamic_cast μ μ¬)IsA<T>()β λ°νμ νμ κ²μ¬ (typeid μ μ¬)- κ°λΉμ§ 컬λ ν° (GC) β UObject λ©λͺ¨λ¦¬ μλ νμ (delete μλν)
BeginPlay()/Tick()β vtable λμ λμ€ν¨μΉ (virtual ν¨μ νΈμΆ)SpawnActor<T>()β λ°νμ κ°μ²΄ μμ±
1
2
3
4
5
6
7
8
9
10
AActor* Actor = GetOwner();
ACharacter* Char = Cast<ACharacter>(Actor); // μ€ν¨ μ nullptr
if (Char) Char->Jump();
if (Actor->IsA<ACharacter>()) { /* ACharacter νμ νμ
*/ }
UMyObject* Obj = NewObject<UMyObject>(this); // GCκ° λ°νμ κ΄λ¦¬
// delete Obj; // β μ λ κΈμ§! GCκ° μλ ν΄μ
AMyActor* Spawned = GetWorld()->SpawnActor<AMyActor>(AMyActor::StaticClass());
볡기:
Cast<T>()= μΈλ¦¬μΌ λ°©μ dynamic_cast; μ€ν¨ μ nullptrUObjectλ GCκ° λ©λͺ¨λ¦¬ κ΄λ¦¬ β μ§μ deleteκΈμ§UPROPERTY()λ§€ν¬λ‘κ° μμ΄μΌ GCκ° λ νΌλ°μ€ μΆμ κ°λ₯- λ°νμ μ±λ₯ λ―Όκ° μ½λ(Tick)μμ
Castλ¨μ© μ£Όμ β μΊμ± κΆμ₯