C++

· C++
소개vcpkg는 microsoft에서 개발한 패키지 매니저로, 파이썬의 pip와 같이 커맨드라인을 통해 패키지를 설치할 수 있도록 하는 프로그램이다. 이 글에서는 내가 직접 Microsoft/vcpkg 레포지토리에 PR을 올려 머지된 경험을 바탕으로 작성되었다.더 자세한 내용은 여기를 참고해보자.순서vcpkg에 새로운 패키지를 업로드하는 과정은 다음과 같다.CMakeList 수정vcpkg 포크(fork) 후 리모트 변경port 작성 후 커밋 & push최종적 PR 보내기vcpkg에서 port란vcpkg에는 우리가 작성한 라이브러리 코드가 들어있지 않고, 저장소의 이름과 버전 SHA 해시를 가지고 있다.우리가 작성해야 하는 port는 각각의 라이브러리의 버전과 설치 방법에 대한 내용이 담겨있는 정보이다.사..
· C++
서론게임 서버 프로젝트에서 로직 스레드를 싱글로 변환했다. 로직스레드가 싱글로 돌아가기 때문에 I/O에서 블로킹이 일어나면 그만큼 처리의 레이턴시가 생기는 것이기 때문에 이를 개선하기 위해 데이터베이스 쿼리를 비동기로 실행하고, 완료 콜백을 호출할 시스템을 구현하기로 했다. 본격 비동기화 시키기따로 데이터베이스 쿼리를 처리할 스레드를 생성할까 했지만, 스레드와 스레드가 데이터를 주고받는것 자체가 지연이 생길 수 밖에 없어 좋지 않아 보였다. 그렇다고 각 쿼리마다 스레드를 파는 것은 너무 효율이 떨어지는 방법이다. 가장 단순한 방법으로 task를 생각했다. task는 promise, future, packaged_task, async 등을 사용해 개발하는 것이다.task의 구현 자체는 스레드의 wrappe..
· C++
C++ 라이브러리 시스템C++은 다른 언어들과 다르게 라이브러리가 소스파일이 아니라 라이브러리 바이너리와 헤더로 나뉘어져 있고,컴파일 과정에 헤더의 경로를 등록시키고, 라이브러리 바이너리를 링크 시켜주어야 한다.그로 인해 새로운 라이브러리를 사용할 때마다 따로 컴파일, include 경로, 라이브러리 링크 등을 설정해주어야 한다.내가 사용한 기존의 방법git에서 submodule로 라이브러리를 추가하고, 배치파일 스크립트를 통해 CMake로 각각을 빌드하고 특정 폴더에 라이브러리 바이너리를 복사했다. 그 후 비주얼 스튜디오 프로젝트 설정에서 라이브러리를 등록해 사용했다.하지만  배치파일 스크립트를 통해 커스텀으로 라이브러리를 컴파일 하기때문에 새로운 라이브러리를 추가할 때마다 빌드 스크립트의 작성과 프로..
· C++
개발 배경MMORPG 팀 프로젝트 기획 중 서버에서 혼자 구현하지 못할 만큼의 컨텐츠를 기획하게 되었다... 이 상황을 해결하기 위해 고민하던 중 포톤에서 사용하던 RPC방식이 떠올렸다.RPC는 네트워크에서 복제된 객체에 대해 원격으로 함수를 호출해 서버에서 따로 로직을 구현하지 않고 클라이언트에서  구현하므로 개발 속도가 빨라지기 때문이다. 구현 이론RPC를 구현하기 위해선 다음 정보를 직렬화해야 한다.메서드 식별용 아이디브로드캐스팅 타깃RPC 호출자 아이디메서드 인수 목록클라이언트에서 RPC를 호출하면 데이터를 직렬화시켜 서버에게 보내고, 서버는 타깃에게 이 직렬화 데이터를 브로드캐스팅 하게 된다. 그 후 클라이언트에서 RPC 데이터를 받게 된다면 메서드 식별 아이디와 메서드 인수 목록을 역직렬화 시..
· 잡다지식
프로그래밍을 할 때 메모리 관리는 필수 불가결하다.프로그래머가 직접 메모리를 할당과 해제를 관리한다면 실수로 인해 사용 중인 메모리가 어떠한 이유로 해제되어 프로그램이 고장 날 수도 있고, 메모리 누수가 일어날 수도 있다. 이러한 문제를 해결하기 위해 직접 할당과 해제를 하지 않고 메모리를 관리하는 여러 시스템이 만들어졌다.이 글에선 메모리를 관리하는 시스템 3가지를 소개하려 한다. 1. 참조 카운팅(Reference Counting)이 방법은 주로 C++에서 사용되는 방법으로, 객체를 참조하는 카운팅을 통해 객체의 할당 해제 시점을 결정하는 방식이다.C++에서 '스마트 포인터'를 사용해 카운팅 한다. 객체를 참조하면 카운트가 1이 늘어나고, 참조를 하는 객체가 소멸된다면 카운트가 1이 줄어든다. 최종적..
나는 메모리 풀을 구현할 때 다음과 같이 구현했다.static T* Pop(){ T* ptr = nullptr; if (!m_pool.empty()) ptr = m_pool.pop(); else ptr = new T; return ptr;}하지만 Pop을 호출하는 순간 엄청난 new의 콜스택이 쌓여 스택 오버플로우가 발생했다. 아무리 생각해도 new가 new를 호출할 일이 뭐가 있지 싶었지만, 얼마 지나지 않아 이유를 찾았다.바로 내가 풀링을 구현한 방식 때문이였다. 클래스에서 매크로를 사용해 new를 오버로딩하게 만들어 new를 호출할 때 오브젝트 풀에서 Pop을 호출하게 하는 식으로 구현했다.ptr = new T;그래서 이 코드에서 또 new를 호출하고 Pop을 하게 만..
메모리 배치 컴퓨터는 한 번에 처리할 수 있는 비트 수를 워드(word)라고 부른다. 만약 컴퓨터가 64비트라면 워드의 크기는 8바이트고, 32비트라면 4바이트이다. 컴퓨터에서 데이터를 한 워드안에 읽어 효율적으로 읽기 위해서 데이터의 크기별로 메모리에 배치한다. 만약 단위가 1이라면 어디에든지 배치가 가능하고, 2라면 2의 배수의 메모리 주소에 배치가 된다. 만약 4바이트 정수형(int) 데이터 하나가 워드와 워드 사이에 존재한다면 2번 연산을 해야한다는 문제가 발생한다. 배치 단위 확인하기 비주얼 스튜디오에서 클래스 위에 마우스 커서를 대보면 맞춤(Alignment): 8바이트라고 정적 검사를 통해 보여준다. IDE에서 확인하는 방법 말고도 소스 코드를 통해 확인하는 방법이 있다. cout
· C++
Format을 왜 해야 할까 winapi나 다른 운영체제의 api를 사용하다 보면 애러가 날 때 애러 메시지가 아니라 에러코드를 리턴한다. 따라서 이 애러가 무슨 애러인지 알기 위해서는 구글링으로 애러코드를 검색해야 한다. 애러코드를 메시지로 구글링으로 메시지를 알아내도 되지만 매번 검색하기는 귀찮다는 문제가 있다. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errCode, /* 애러 코드 */ 0, (LPTSTR)&errorMessage, /* 애러 메세지 */ 0, NULL); winapi에서는 애러코드를 메시지로 변환해 주는 FormatMessage라는 함수가 있다. 하지만 이 함수를 호출하기 위해..
index1207
'C++' 태그의 글 목록