4월, 2017의 게시물 표시

최근 근황

오랜만에 글을 쓰는 거 같다..
최근 근황은 뭐 계속 회사 생활의 반복이다.. 눈깜짝하니 입사한지도 1년이 어느새 훌쩍넘었다. 뭔가 해보고 싶은게 많은데, 회사 다니면서 출퇴근 시간도 길고, 내가 체력도 안좋고 부지런한 편도 아니라서 진짜 회사만 다니기 벅찼던 것 같다.
그래도 나름 뭔가 해보려고 최근에 2가지 활동을 했었다.     그중에 하나는 컨트리뷰톤이다. 작년이나 올해 초까지만해도 오픈소스 활동을 했었는데, 회사다니면서 자연스레 멈추게 되었다. 다시 한번 오픈소스 활동을 시작하기 위한 계기를 삼으려고 컨트리뷰톤이라는 프로그램에 참여하여 uftrace 라는 C/C++ function tracing 툴 프로젝트에서 활동을 했다. 현재는 컨트리뷰톤 활동은 끝났고, 이번 달 말에 폐회식?시상식? 이 있을 예정이다.     또 하나는 블록체인 스터디이다. 반년전쯤부터인가 블록체인쪽에 관심이 생겨서 한번 공부를 해보려고 스터디를 하게 되었다. 스터디는 현재 진행형이다.
회사를 다니면서 이렇게 2가지 활동을 동시에 했다. 이 활동들에 내가 투자하려고 했던 시간/에너지 양이 대략 있었는데, 막상 해보니 실제로 투자한 시간은 내 예상의 20% 도 안되는 것 같다. 신규 기능개발로 인해 회사 일이 최근에 바쁘기도 했고, 생각보다 내가 시간과 자기관리를 제대로 못했다. 시간투자를 많이 못한게 아쉽긴 한데, 일단 뭐라도 해본 것에 의의를...
아 그리고, 최근에 우리 팀 우리 파트 채용공고를 새로 냈다. 기존의 채용 공고가 너무 모호하고 매력이 떨어진다고 생각해서 내가 건의를 해서 채용공고의 내용을 바꿔봤다.

채용공고 보기/숨기기
모집부분 - C++ 기반 공용 모듈 개선 및 개발 - C++ 기반 엔진 모듈 개선 및 개발 담당업무 - 사내 C++ 공용 라이브러리 개선 및 개발 - C++ 기반 악성코드 탐지/치료 엔진 개선 및 개발 - 코드 품질 및 개발 프로세스 개선 자격요건 - C++ 활용에 자신 있는 분 - 능동적이고 적극적으로 업무를 수행하시는 분 우대요건 …

[Effective Modern C++] Chapter 6. 람다 표현식 [항목 31~34]

Chapter 6. 람다 표현식 항목 31. 기본 갈무리 모드를 피하라. 참고로, 갈무리는 'capture'를 의미한다. (첨엔 어색했으나 나도 이제 완전히 이 번역에 익숙해져버렸다.)
기본 갈무리 모드 (default capture mode)는 '참조 갈무리 모드'와 '값 갈무리 모드'가 있다. 기본 갈무리 모드를 피해야 하는 이유는 크게 dangling reference 위험과 명시적이지 않다는 점(그래서 착각/실수 할 수 있다는 점) 때문이다.
일단, 참조 갈무리 모드에서 dangling reference 문제가 발생할 수 있다는 것은 너무 당연하고, 값 갈무리 모드에서도 pointer가 capture되는 경우에 그러한 문제가 발생 할 수 있다는 것은 당연하다.
사실 결정적인 문제는 명시적이지 않다는 점이다. 이로 인해 문제가 발생 할 수 있을 만한 상황을 정리하면 다음과 같다.
1. this pointer의 캡처
    - 숨겨져있던 this pointer가 캡처됨으로 인해 dangling pointer 등의 문제가 발생할 수 있다.
2. 람다표현식을 복붙(Copy&Paste) 할 경우, 실수할 가능성이 커진다.
    - 유용한 람다표현식을 그대로 다른 곳에서 쓸 경우가 있을 수 있다. 이 경우, capture list가 명시적이지 않아서 문제들이 발생할 소지가 있다.
3. 전역 변수나 static 같이 global scope를 가진 변수들 (즉, non-automatic variable들)의 값이 복사로서 capture될 것이라는 착각을 할 수 있다.
    - 오직 automatic variable들(즉, 지역변수들) 만 capture될 수 있는데, 기본 값 갈무리 모드를 사용하면, non-automatic variable들도 값 복사로서 capture될 것이라는 착각을 할 여지가 있다.

즉, 기본 갈무리 모드의 문제는 결국 '명시적이지 않다'는 것이다. 필요한 것들만 명시적으로 …

PyPy RPython Translation Toolchain

이미지
그 동안 PyPy를 단순히 JIT을 지원하는 빠른 python implementation 이라고만 알고 있었다.그런데 알고 보니 단순한 python implementation 이상의 의미를 갖는 상당히 멋있는 프로젝트였다.

PyPy는 2가지 파트로 나뉜다.
1. RPython 문법으로 작성된 Python Interpreter
2. RPython Translation Toolchain

1번의 python interpreter를 2번의 toolchain에 넣으면, JIT, garbage collector 등의 기능이 첨가된 C언어로 된 interpreter가 결과로서 나온다.
???!! 매우 놀라울 것이다. 2번의 toolchain은 Python 소스 코드나 syntax trees 에 대한 정보는 전혀 가지고 있지 않는다. 그런데 JIT과 garbage collector를 비롯한 기능들을 첨가해준다니?!
그래서 내가 멋있다고 한 것이다...


(출처 : https://www.toptal.com/python/why-are-there-so-many-pythons)

PyPy의 구조를 그림으로 보자면 위와 같다. (PyPy Interpreter가 1번, PyPy compiler가 2번에 해당한다.)


(출처 : http://rpython.readthedocs.io/en/latest/translation.html)

RPython translation toolchain의 실제 플로우를 그림으로 보자면 위와 같다. 기본적으로 RPython으로 작성된 interpreter 코드가 필요하고 추가적으로 low level hint들을 통해 세부적인 과정에 참여할 수 있다. 그리고 translation toolchain의 backend는 현재 C언어만 가능하지만, 설계 상 더 추가가 가능한 구조이다.
그리고 이러한 RPython Translation Toolchain을 이용하면 Python 뿐만 아니라 모든 언어들의 'JIT'ed Interpreter를 얻을 수 있다.
https://bit…

[Effective Modern C++] Chapter 5. 오른값 참조, 이동 의미론, 완벽 전달 [항목 23~30]

Chapter 5. 오른값 참조, 이동 의미론, 완벽 전달 항목 23. std::move와 std::forward를 숙지하라.#include <iostream> class Example { public: Example() = default; Example(const Example &) { std::cout << "copy constructor" << std::endl; } Example(Example &&) { std::cout << "move constructor" << std::endl; } Example(const Example &&) { std::cout << "const move constructor" << std::endl; } }; /* std::forward is meaningful only for universal reference in template. */ void test1(Example ex) { std::cout << "Test 1" << std::endl; Example a(std::forward<Example>(ex)); // move constructor Example b(std::forward<Example&>(ex)); // copy constructor Example c(std::forward<Example&&>(ex)); // move constructor } void test2(Example& ex) { std::cout << "Test 2" << std::endl; Example a(std::forward<Example…

[Effective Modern C++] Chapter 4. 똑똑한 포인터 (Smart Pointer) [항목 18~22]

Chapter 4. 똑똑한 포인터 (Smart Pointer) 항목 18. 소유권 독점 자원의 관리에는 std::unique_ptr를 사용하라. 보통 smart pointer를 처음 접한 사람들은 std::shared_ptr만을 남용(?)하는 경향이 있다. 그러나 std::shared_ptr이 매우 강력한 존재이긴 하지만 크게 2가지 측면에서 단점이 있다. 첫 번째는 overhead이다. 참조 계수를 관리하기 위해 어쩔 수 없이 overhead가 존재한다. 두 번째는 돌이킬 수 없다는 점이다. 한번 std::shared_ptr에 pointer를 물리고 나면 다시는 일반 pointer로 복귀할 수 없다. (단순히 .get()을 쓰면 raw pointer를 받을 수 있을 뿐이다. 여전히 프로그램 어딘가에서 포인터를 참조할 수 있을 수 있다.)
이러한 단점들 때문에 나는 기본적으로 std::unique_ptr을 사용한다. std::unique_ptr은 덜 강력하지만 위 2가지 단점이 없다. 추가적인 메모리를 요구하는 커스텀 삭제자를 지정하지 않는다면 performance는 raw pointer와 사실상 동일하고, std::unique_ptr를 사용하다가 적합하지 않은 상황이 오면 언제든지 정책을 raw pointer나 std::shared_ptr등으로 바꿀 수 있다.
참고) raw pointer, std::unique_ptr, std::shared_ptr의 '생성 및 삭제' 성능 비교 : http://www.modernescpp.com/index.php/memory-and-performance-overhead-of-smart-pointer
특히 어떻게 쓰일 지 모르는 포인터를 반환해야 하는 경우는 std::unique_ptr를 쓰는 것이 좋다. std::unique_ptr은 어떤 형태로든지 변환이 가능하기 때문이다. 특별한 목적이 있는 경우가 아니라면, 팩토리 함수등에서 std::shared_ptr 을 반환하는 것은 좋지 않은 습관이다. 하지만 s…

이 블로그의 인기 게시물

[Effective C++ 3판] Chapter 1. C++에 왔으면 C++의 법을 따릅시다. (항목 1~4)

개발다운 개발에 대해...

최근 근황