문제
CS / 운영체제
1.
프로세스와 스레드의 차이로 가장 적절한 것은?
- 프로세스는 스택을 공유하고 스레드는 공유하지 않는다
- 스레드는 같은 메모리 공간을 공유할 수 있다
- 프로세스는 문맥 교환(Context Switching)이 불가능하다
- 스레드는 각각 독립적인 코드 영역을 가진다
2.
뮤텍스(Mutex)와 세마포어(Semaphore)의 차이 설명으로 올바른 것은?
- 세마포어는 오직 1개의 스레드만 접근 가능하다
- 뮤텍스는 소유 개념(owner)이 존재한다
- 세마포어는 동기화에 사용할 수 없다
- 뮤텍스는 카운팅이 가능하다
3.
가상 메모리를 사용하는 가장 큰 이유는?
- CPU 속도를 증가시키기 위해
- 디스크 사용을 제거하기 위해
- 실제 메모리보다 큰 주소 공간 제공
- 스레드 생성 속도 향상
자료구조 / 알고리즘
4.
BFS에 가장 적합한 자료구조는?
- Stack
- Queue
- Tree
- Heap
5.
시간복잡도가 가장 낮은 정렬은 평균 기준 무엇인가?
- Bubble Sort
- Insertion Sort
- Merge Sort
- Selection Sort
6.
unordered_map의 평균 탐색 시간복잡도는?
- O(1)
- O(logN)
- O(N)
- O(NlogN)
C++
7.
다음 코드의 출력 결과는?
#include <iostream>
using namespace std;
class A{
public:
A(){ cout<<"A"; }
~A(){ cout<<"B"; }
};
int main(){
A a;
}
- A
- AB
- BA
- 컴파일 에러
8.
virtual 함수의 주된 목적은?
- 함수 오버로딩
- 다형성 구현
- 메모리 절약
- 컴파일 속도 향상
9.
다음 중 스마트 포인터가 아닌 것은?
- shared_ptr
- weak_ptr
- auto_ptr
- unique_ptr
10.
참조(reference)에 대한 설명으로 올바른 것은?
- nullptr 가능
- 선언 후 다른 변수 참조 가능
- 반드시 초기화 필요
- 주소값 연산 불가능
그래픽스
11.
렌더링 파이프라인 순서로 가장 적절한 것은?
- Rasterization → Vertex Shader → Fragment Shader
- Vertex Shader → Rasterization → Fragment Shader
- Fragment Shader → Vertex Shader → Rasterization
- Rasterization → Fragment Shader → Vertex Shader
12.
노멀 벡터(normal vector)의 주된 역할은?
- 카메라 이동 계산
- 물체 이동 계산
- 조명 계산
- 애니메이션 처리
13.
FPS 게임에서 프러스텀 컬링(Frustum Culling)을 사용하는 이유는?
- 네트워크 최적화
- 사운드 처리 감소
- 화면 밖 객체 렌더링 제거
- 텍스처 압축
14.
행렬(Matrix)을 사용하는 가장 큰 이유는?
- 색상 저장
- 충돌 처리
- 좌표 변환
- 메모리 압축
게임 개발 / 엔진
15.
오브젝트 풀링(Object Pooling)의 목적은?
- GPU 사용 증가
- 메모리 단편화 감소 및 생성 비용 절약
- 네트워크 패킷 감소
- 쉐이더 최적화
16.
델타 타임(delta time)을 사용하는 이유는?
- FPS 제한
- 프레임레이트에 관계없이 일정한 움직임 구현
- 메모리 최적화
- GPU 동기화
단답형
17.
Deadlock 발생 조건 4가지를 쓰시오.
18.
깊은 복사(Deep Copy)와 얕은 복사(Shallow Copy)의 차이를 설명하시오.
19.
CPU 캐시(Cache)를 사용하는 이유는?
20.
Vertex Shader와 Fragment Shader의 차이를 설명하시오.
정답
정답 및 해설
1.
정답: 2
스레드는 같은 프로세스 내에서:
- 코드 영역
- 데이터 영역
- 힙 영역
을 공유한다.
대신 스택은 각자 가진다.
2.
정답: 2
뮤텍스는 “소유권(owner)” 개념이 있다.
- lock 건 스레드만 unlock 가능
세마포어는 단순 카운터 기반이라 소유 개념이 없다.
3.
정답: 3
가상 메모리의 핵심 목적:
- 실제 RAM보다 큰 메모리 공간 제공
- 프로세스 격리
- 메모리 관리 효율화
4.
정답: 2
BFS는 FIFO 구조이므로 Queue 사용.
DFS는 Stack(또는 재귀).
5.
정답: 3
평균 시간복잡도:
- Bubble → O(N²)
- Insertion → O(N²)
- Selection → O(N²)
- Merge → O(NlogN)
6.
정답: 1
unordered_map은 해시 기반.
평균:
O(1)O(1)
최악은 충돌 시 O(N).
7.
정답: 2
생성자 → A 출력
main 종료 시 소멸자 → B 출력
결과:
AB
8.
정답: 2
virtual 함수는 런타임 다형성(polymorphism)을 위해 사용.
대표 예시:
Base* obj = new Derived();
obj->func();
Derived의 함수 호출 가능.
9.
정답: 3
auto_ptr은 C++17에서 제거됨.
소유권 이동 방식이 위험해서 deprecated.
현대 C++에서는:
- unique_ptr
- shared_ptr
- weak_ptr
사용.
10.
정답: 3
참조(reference)는:
- 선언 즉시 초기화 필요
- 다른 대상 참조로 변경 불가
- null 불가능
11.
정답: 2
렌더링 파이프라인 기본 흐름:
Vertex Shader
→ Rasterization
→ Fragment(Pixel) Shader
12.
정답: 3
노멀 벡터는 빛 방향 계산에 사용.
조명 공식(Lambert 등)에서 핵심.
13.
정답: 3
카메라 시야 밖 객체를 렌더링하지 않아 성능 최적화.
게임 엔진에서 매우 중요.
14.
정답: 3
행렬(Matrix)은:
- 이동(Translation)
- 회전(Rotation)
- 크기변환(Scaling)
같은 좌표 변환 처리.
15.
정답: 2
오브젝트를 미리 생성 후 재사용해서:
- new/delete 감소
- GC 부담 감소
- 메모리 단편화 감소
총알 시스템에서 자주 사용.
16.
정답: 2
델타 타임 사용 이유:
FPS가 달라도 동일한 속도 유지.
예시:
position += speed * deltaTime;
17.
Deadlock 발생 조건 4가지
- 상호 배제(Mutual Exclusion)
- 점유 대기(Hold and Wait)
- 비선점(No Preemption)
- 순환 대기(Circular Wait)
모두 만족 시 데드락 가능.
18.
Deep Copy vs Shallow Copy
얕은 복사(Shallow Copy)
주소값만 복사.
a.ptr = b.ptr;
문제:
- 이중 해제(double free)
- 원본 변경 영향
발생 가능.
깊은 복사(Deep Copy)
실제 데이터까지 새로 복사.
ptr = new int(*other.ptr);
독립 메모리 사용.
19.
CPU Cache 사용하는 이유
RAM보다 훨씬 빠른 메모리로:
- 자주 사용하는 데이터 저장
- 메모리 접근 시간 감소
- CPU 대기 최소화
즉, 성능 향상 목적.
20.
Vertex Shader vs Fragment Shader
Vertex Shader
정점 단위 처리.
주요 역할:
- 좌표 변환
- 뼈대 애니메이션
- MVP Matrix 적용
Fragment Shader
픽셀 단위 처리.
주요 역할:
- 색상 계산
- 조명 계산
- 텍스처 처리
c++ 문제
1. 생성자/소멸자 순서
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A"; }
~A() { cout << "B"; }
};
class C : public A {
public:
C() { cout << "C"; }
~C() { cout << "D"; }
};
int main() {
C obj;
}
출력 결과는?
2. Virtual Destructor
#include <iostream>
using namespace std;
class Base {
public:
~Base() {
cout << "Base";
}
};
class Derived : public Base {
public:
~Derived() {
cout << "Derived";
}
};
int main() {
Base* ptr = new Derived();
delete ptr;
}
출력 결과와 문제점을 설명하시오.
3. Dangling Pointer
#include <iostream>
using namespace std;
int* func() {
int x = 10;
return &x;
}
int main() {
int* p = func();
cout << *p;
}
무슨 문제가 발생하는가?
4. const 함정
#include <iostream>
using namespace std;
int main() {
const int x = 10;
int* p = (int*)&x;
*p = 20;
cout << x;
}
결과를 예측하시오.
5. Vector Reallocation
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
v.push_back(1);
int* p = &v[0];
v.push_back(2);
cout << *p;
}
문제가 발생할 수 있는 이유는?
6. 복사 생성자 호출 횟수
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A"; }
A(const A&) { cout << "B"; }
};
void func(A a) {}
int main() {
A obj;
func(obj);
}
출력 결과는?
7. Move Semantics
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A"; }
A(const A&) {
cout << "Copy";
}
A(A&&) {
cout << "Move";
}
};
A func() {
A a;
return a;
}
int main() {
A obj = func();
}
가능한 출력 결과들을 설명하시오.
8. Virtual Function in Constructor
#include <iostream>
using namespace std;
class Base {
public:
Base() {
func();
}
virtual void func() {
cout << "Base";
}
};
class Derived : public Base {
public:
void func() override {
cout << "Derived";
}
};
int main() {
Derived d;
}
출력 결과는?
9. delete vs delete[]
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A"; }
~A() { cout << "B"; }
};
int main() {
A* arr = new A[3];
delete arr;
}
문제점을 설명하시오.
10. Pure Virtual
#include <iostream>
using namespace std;
class Base {
public:
virtual void func() = 0;
};
class Derived : public Base {
};
int main() {
Derived d;
}
컴파일 결과는?
11. shared_ptr 순환참조
#include <memory>
using namespace std;
class B;
class A {
public:
shared_ptr<B> b;
};
class B {
public:
shared_ptr<A> a;
};
int main() {
auto a = make_shared<A>();
auto b = make_shared<B>();
a->b = b;
b->a = a;
}
문제점은?
12. sizeof 함정
#include <iostream>
using namespace std;
class A {
int a;
char b;
};
int main() {
cout << sizeof(A);
}
32bit/64bit 환경에서 왜 예상보다 크게 나올 수 있는가?
13. UB 문제
#include <iostream>
using namespace std;
int main() {
int x = 1;
cout << x++ + ++x;
}
출력 결과는?
14. STL iterator invalidation
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> v = {1,2,3};
auto it = v.begin();
v.push_back(4);
cout << *it;
}
왜 위험한가?
15. polymorphism 함정
#include <iostream>
using namespace std;
class Base {
public:
void func() {
cout << "Base";
}
};
class Derived : public Base {
public:
void func() {
cout << "Derived";
}
};
int main() {
Base* p = new Derived();
p->func();
}
출력 결과와 이유는?
정답
1. 생성자/소멸자 순서
정답:
ACDB
이유
생성 순서:
- 부모 생성자 A
- 자식 생성자 C
소멸 순서:
- 자식 소멸자 D
- 부모 소멸자 B
즉:
A C D B
2. Virtual Destructor
정답:
Base
문제점
부모 소멸자가 virtual이 아니므로:
delete ptr;
시 Derived 소멸자가 호출되지 않는다.
즉:
- 자식 자원 해제 실패
- 메모리 누수 가능
올바른 코드
virtual ~Base()
게임회사 면접 단골.
3. Dangling Pointer
문제
return &x;
지역변수 x는 함수 종료 시 소멸.
따라서:
p
는 dangling pointer.
이후 접근은 UB(Undefined Behavior).
4. const 함정
정답
UB.
출력은:
- 10
- 20
- 이상한 값
모두 가능.
이유
const int x
를 강제로 수정.
컴파일러는 const 값을 최적화할 수 있음.
그래서 실제 메모리 값과 사용 값이 달라질 수 있다.
5. Vector Reallocation
문제
v.push_back(2);
시 vector 재할당(reallocation) 가능.
그러면 내부 배열 주소 변경.
따라서:
p
는 무효 포인터가 된다.
(iterator invalidation)
6. 복사 생성자 호출
정답:
AB
이유
A obj;
→ 기본 생성자 A
func(obj);
값 전달(pass by value)
→ 복사 생성자 B
7. Move Semantics
가능한 출력:
Case 1
AA
RVO(Return Value Optimization)
복사/이동 생략.
Case 2
AMove
이동 생성자 호출.
핵심
현대 컴파일러는 NRVO/RVO 최적화를 자주 수행.
면접 포인트:
"반드시 Move가 호출되는 건 아니다."
8. Virtual Function in Constructor
정답:
Base
이유
생성자 실행 중에는 아직 Derived 부분이 완성되지 않음.
따라서 virtual dispatch가 동작하지 않고:
Base::func()
호출.
이거 매우 유명한 함정.
9. delete vs delete[]
문제
delete arr;
배열을:
new A[3]
로 생성했으면 반드시:
delete[]
사용해야 한다.
왜 위험한가
- 소멸자 일부만 호출 가능
- UB 발생
10. Pure Virtual
결과
컴파일 에러.
이유
virtual void func() = 0;
순수 가상 함수 존재.
Derived가 override 안 했으므로 여전히 추상 클래스.
객체 생성 불가능.
11. shared_ptr 순환참조
문제
A ↔ B 서로 shared_ptr 보유.
참조 카운트가 0이 되지 않음.
즉:
- 메모리 누수 발생
해결
한쪽을:
weak_ptr
로 변경.
12. sizeof 함정
이유
패딩(padding) 때문.
예:
int 4byte
char 1byte
하지만 정렬(alignment)을 위해:
8byte
가 될 수 있음.
핵심
CPU 메모리 접근 최적화 목적.
게임 엔진 최적화에서 중요.
13. UB 문제
x++ + ++x
정답:
UB.
이유
한 표현식 내에서:
- x를 여러 번 수정
- evaluation order 미정
컴파일러마다 다를 수 있음.
14. iterator invalidation
문제
v.push_back(4);
시 vector 재할당 가능.
그러면:
it
무효 iterator.
접근하면 UB.
15. polymorphism 함정
정답:
Base
이유
func()
가 virtual이 아니다.
따라서 정적 바인딩.
포인터 타입 기준:
Base*
의 함수 호출.
'CS' 카테고리의 다른 글
| GPU 렌더링 파이프 라인 (2) | 2026.05.19 |
|---|---|
| 운영체제 주요 개념 정리 (1) | 2026.05.16 |