전체 글 143

Select model

Select model이란 소켓이 읽기, 쓰기 또는 둘 다 준비가 된 상황인지 확인하는 방법이다. 덕분에 소켓 입출력 등이 성공할 때 까지 계속 대기한다던가, 성공할 때 까지 계속 시도한다던가 하는 상황을 어느정도 해결해줄 수 있다. 방법 키워드 : select, fd_set, FD_ZERO, FD_SET, FD_ISSET 우선 fd_set 형 변수(소켓 셋)를 선언한다. 소켓 셋은 검사할 소켓의 집합이라고 생각하면 된다. 여기서 검사란 위에 설명한 소켓이 준비가 되었는지 아닌지에 대한 검사이다. FD_ZERO 함수로 소켓 셋을 초기화 한다. FD_SET 함수로 소켓 셋에 소켓을 추가한다. select 함수로 소켓 셋 안에 있는 소켓들 중 읽기 혹은 쓰기가 준비된 소켓만 남기고 소켓 셋에서 지운다. FD..

Socket Options

Socket Option이란 우리가 네트워크 통신을 위해 사용하는 Socket은 기본 사용법 대로만 하면 기본적인 통신하는 데에 문제가 없지만, Socket의 세부 옵션 설정을 통해 더 원하는 동작을 구현할 수 있다. 그것은 setsockopt 함수를 사용해서 가능하다. 또한 getsockopt 함수를 통해 현재 설정된 소켓의 옵션을 확인할 수도 있다. setsockopt 함수의 기본 사용법 setsockopt 함수는 보통 다음과 같은 형태로 사용한다. setsockopt(, , , , ); 여기서 이란 우리가 설정 할 주인공(?)의 레벨을 말한다. 예를 들면 우리가 설정 할 옵션이 소켓의 옵션인지, IPv4의 옵션인지, TPC 프로토콜의 옵션인지를 정하는 인자이다. 따라서 소켓의 옵션을 설정해주고 싶다..

STL Allocator

이 프로젝트에서 메모리 할당을 관리하기 위해 커스텀 Allocator들을 만들었다. 그런데 c++에서 기본적으로 제공하는 STL에서는 내부에서 원래 있던 new, delete를 사용할 것이다. 즉 STL을 사용하면 우리가 힘들게 만든 Allocator로 메모리를 관리할 수 없다. 따라서 우리는 STL사용 시에도 커스텀 Allocator를 사용하도록 만들 것이다. 그것이 STL Allocator이다. STL Allocator 만들기 사제 Allocator가 STL에 사용되기 위한 몇 가지 요구사항이 존재한다. tempalte를 사용할 것. using value_type 가 존재할 것. T* allocate(size_t count) 함수가 존재할 것. void deallocate(T* ptr, size_t ..

Stomp Allocator

Stomp Allocator는 기존의 new, delete의 메모리 오염 문제를 해결하기 위해 정의한 클래스이다. 메모리 오염 메모리 오염이란 메모리가 해제되었는데도 잘못 사용되는 문제를 말한다. 예를 들면 아래와 같은 상황에서 발생할 수 있다. class Knight { public: Knight() { _hp = 100; } Knight(int hp) :_hp(hp){} ~Knight() {} int _hp; }; int main() { Knight* test = new Knight(); test->_hp = 100; delete test; test->_hp = 200; //여기! } 마지막 줄에서 이미 해제된 포인터인 test의 멤버 변수 값을 수정하고 있다. 명백히 잘못된 코드이지만 이 코드는 실..

스마트 포인터

스마트 포인터란 스마트 포인터란 포인터의 부족했던 기능적인 면들을 보완한 것이다. 스마트 포인터는 shared_ptr, weak_ptr, unique_ptr 세 종류가 있다. 그럼 포인터의 어떤 부족한 면을 보완했는지 알아보자. shared_ptr shared_ptr은 여러 포인터 변수가 하나의 객체를 참조하고 있는 상황에서 객체가 delete 되었을 때, 그 객체를 참조하고 있던 포인터 변수들은 이를 모르고 계속 참조하고 있는 상황을 해결하기 위한 스마트 포인터이다. 작동 방식은 기존 포인터를 포인터와 그 포인터가 참조하고 있는 객체를 몇 개의 포인터 변수가 참조하고 있는지 갯수를 가지고 있는 변수를 담은 클래스로 관리하는 것이다. 여기서 중요한 것은 몇 개의 포인터가 참조하고 있는지를 담은 변수를 컨..

C++ 2022.03.29

순환문제

순환문제란 shared_ptr을 서로 교차해서 참조하는 경우에 그 포인터를 해제시켜도 해제되지 않고 메모리에 계속 남아있는 현상을 말한다. 아래 상황을 보자. (참고로 코드를 직접 실행해 보지는 않았음 그냥 상황만 보셈) class Knight { sharerd_ptr _target; } void main() { sharerd_ptr k1 = make_shared(); sharerd_ptr k2 = make_shared(); k1._target = k2; k2._target = k1; k1 = nullptr; k2 = nullptr; } 위처럼 두 Knight 객체의 스마트 포인터가 서로를 참조하고 있을 때, k1과 k2가 서로의 Reference Count를 증가시키고 있다. 이 때 우리 생각대로라면 ..

C++ 2022.03.28

NAT(Network Address Translation)

NAT이란? NAT(Network Address Translation)은 네트워크 주소 변환이라고 해석된다. 그럼 무엇을 어떻게 변환해주느냐? Internal(Private) Address와 External(Public) Address를 변환해주는 것이 NAT이다. 여기서 Internal Address와 eAddress가 무엇인지 알 필요가 있다. 사실 Internal IP Address와 Internal Port, External IP Address와 External Port가 있는데 그냥 내맘대로 묶어서 Internal Address와 Private Address로 불렀음. Internal Address : 내부 주소라는 뜻으로, Private Address, 사설 아이피 등으로도 불린다. IANA(..

STL 컨테이너별 간략 특징 정리

C++ STL에는 여러 종류가 있다. 대표적으로 많이 사용하고 중요한 것들 위주로 알아보자. vector list deque(double-ended queue) 컨테이너 어댑터 queue priority queue stack 연관 컨테이너 정렬되는 연관 컨테이너 map set multiset multimap 정렬 안되는 연관 컨테이너 unordered set(hash set) unorderd map(hash map) vector 벡터는 배열을 기반으로 만들어졌다. 따라서 배열의 특징을 전부 가지고 있다. 그러나 그냥 배열은 그 크기가 고정적이라는 치명적인 단점이 있다. 그래서 벡터는 이 단점을 해결하기 위해 어떤 방식을 사용한다. 그 방식이란, 배열이 다 찼는데 삽입을 하면 원래 배열보다 더 큰 새로운 ..

C++ 2022.02.21

DeadLockProfiler

데드 락 방지 멀티 쓰레드에서 lock을 사용하다 보면 프로그래머의 실수로 데드 락이 발생할 수 있다. 이런 데드 락을 피하기 위해서는 프로그래머가 lock을 사용할 때 순서를 주의해서 사용해야한다. 그러나 사람은 실수를 하기 때문에 이를 보완해줄 방법이 있으면 좋을 것 같다. 데드 락을 방지하는 방법중 하나로 lock을 걸 때 현재 걸린 lock들의 상황을 파악해 이 lock이 데드락을 유발할 가능성이 있는지 검사하는 것이다. 이것이 이 프로젝트에 적용된 DeadLockProfiler 이다. 원리 데드 락은 lock 내부에서 서로의 lock이 풀릴 때까지 무한히 대기하는 현상이다. 이 서로를 기다린다는 것의 의미를 잘 생각해보자. 이 말은 lock들의 관계를 그래프로 나타내었을 때 사이클을 이루게 되면..

ReadWrite Lock

필요성 어떤 공유 데이터를 참조하는 여러 쓰레드가 있다고 가정하자. 이 쓰레드들은 평상시에는 이 공유 데이터를 읽기만 한다. 그런데 아주 드문 경우에, 예를 들면 대략 1주일에 한 번 정도 이 공유 데이터를 수정하는 일이 벌어진다고 해보자. 사실 모든 쓰레드가 읽기만 한다면 Lock을 해줄 필요가 없다. Lock이 필요한 이유는 데이터 수정이 일어났을 때 쓰레드가 잘못 된 데이터를 읽게 될 가능성이 있기 때문이다. 그런데 위의 경우에서 1주일에 한 번 있는 데이터 수정 때문에 모든 읽기 작업에도 mutex를 사용해 Lock을 걸자니 매우 비효율적이라는 생각이 든다. 이런 경우 ReadWriteLock을 사용한다. 사용방식 ReadWriteLock은 ReadLock과 WriteLock으로 나누어진다. Re..