본문 바로가기

Library

템플릿 메서드를 사용하여 자바의 리소스를 관리하라 자바가 등장한 초창기 무렵을 생각해 봤을 때, 자동 메모리 관리 기능은 메모리를 직접 관리해야 하는 고통에 시달리던 프로그래머들에게 구세주처럼 여겨졌다. 그러나, 자바가 점점 그 영역을 넓혀감에 따라, 자동 메모리 관리 기능은 좋기만 한 것이 아니라는 점 역시 드러나게 되었다. 파이널라이저(finalizer)의 실행 시점은 자바 VM 구현에 따라 천차만별이며, 가비지 컬렉터(garbage collector)가 실행될 때 모든 자바 스레드가 순간적으로 정지해야 한다는 점은 특정 영역에서 치명적인 단점이다. 특히, 예외 처리 및 일반화 프로그래밍과 맞물리면서, 안전하게 리소스를 관리하는 것은 쉽지 않은 일이 되었다. C++의 RAII(Resource Acquisition Is Initialization) 기.. 더보기
외부 저장 장치에 저장한 파일이 나타나지 않는다면 추가 SD 카드를 가지지 않는 안드로이드 폰을 사용할 때, 앱 개발 도중 외부 저장 공간에 파일을 저장했음에도 윈도우 탐색기에서 저장한 파일을 볼 수 없는 경우가 있다. 이것은 아직 고쳐지지 않은 안드로이드의 버그인데, 폰을 재부팅해야 최근에 저장한 파일을 볼 수 있다. 재부팅이 귀찮다면, 저장 장치에 대한 미디어 스캔을 수행하는 앱을 사용할 수도 있다. 안드로이드의 API는 내부, 외부 개념을 사용하여 저장 장치를 구별하지만, 사실 외부 저장 장치는 추가 SD 카드만을 의미하는 것이 아니다. 따라서, 추가 SD 카드를 지원하지 않는 안드로이드 폰을 사용한다면, getExternalStorageDirectory()의 결과는 폰에 따라 다르게 나타날 수 있다. 메모리 부족에 시달렸던 과거의 폰들과 달리, .. 더보기
boost::program_options: getopt()을 사용할 수 없을 때 C/C++을 사용하여 콘솔 프로그램을 작성할 때, 프로그램의 옵션를 처리해야 할 필요가 있다. 간단한 옵션 한 두개가 아니라, 제대로 된 옵션 처리를 구현하는 것은 간단한 일이 아니다. UNIX 계열 프로그램들은 하이픈(-) 기호를 사용하여 각 토큰이 프로그램에서 필요로 하는 옵션이라는 것을 나타내며, 보통 한 글자를 사용한다. GNU는 더블 하이픈을 사용하여 한 글자 이상의 문자열을 사용하여 옵션를 나타낸다. 문제는, 옵션를 제대로 처리하는 것은 간단한 일이 아니라는 것이다. 제일 먼저, 실행 시점에서 주어지는 인자들의 집합을 토큰으로 분리해야 하며, 각 토큰들은 순서 의존적인 추가 설정값을 가질 수도 있다. 또, 특정 토큰들은 위치에 상관없이 나타날 수도 있다. 이 요구 사항들은 짧은 시간 안에 완벽.. 더보기
C++는 C가 아니다: 이식성 많은 사람들이 알고 있겠지만, C++ 언어와 C 언어는 많은 부분을 공유하지만, C++ 언어는 공식적으로 C 언어를 계승하는 것은 아니다. C++ 표준화 의원회와 C 표준화 의원회는 서로 긴밀히 협조하기는 하지만, 같은 개발 공동체가 관리하고 있지 않다. 물론, C#과 C의 관계보다는, C++과 C의 관계가 훨씬 밀접하다. 그러나, C++의 복잡한 기능 때문에 고질적으로 컴파일러의 이식성 문제가 따라다니며, 어떤 플랫폼에서도 C++로 작성된 코드를 직접 바인딩하는 것은 쉬운 문제가 아니다. 안드로이드는 NDK를 통해 C/C++를 사용하여 시스템 내부로 접근할 수 있지만, NDK는 성능이 중요한 영역에서 보조적인 수단일 뿐이며, 프레임워크 개발 언어인 자바를 대체할 수 없다. 더구나, 안드로이드가 사용하는.. 더보기
커스텀 할당자를 작성할 때 construct() 호출 문제 C++ 커스텀 할당자를 작성할 때 구현하기 까다로운 부분 중 하나는 std::allocator의 construct()와 destory() 멤버 함수이다. 이들은 개체가 생성되거나 파괴될 때 명시적으로 개체의 생성자와 소멸자를 호출하는 함수들이고, destroy()의 경우 명시적으로 소멸자를 호출하는 것이 전부이다. 문제는 construct()이다. construct()는 replacement new를 사용하여 확보한 메모리 공간에 개체를 실제로 생성하여 배치하는 역할을 한다. 그런데, 개체가 초기값 없이 생성될 경우, construct()는 항상 개체가 생성될 때의 초기값을 요구하기 때문에 construct()를 일반적으로 사용하기는 어렵다. allocator alloc; dummy *p = alloc... 더보기
CygWin Portable Install 윈도우에서 가상 머신을 사용하지 않고 유닉스 환경을 사용하는 방법 중 가장 대표적인 것은 CygWin이다. CygWin은 cygwin1.dll을 사용해서 POSIX 함수들을 구현하기 때문에, 많은 유닉스 프로그램들을 그대로 컴파일해서 사용할 수 있다. CygWin와 자주 비교되는 MSYS는 사실 CygWin에서 파생된 프로젝트다. CygWin이 호환성을 최우선으로 하는 것과 달리, MSYS는 윈도우 환경에서 GNU 툴들을 사용할 수 있도록 호환성을 제공하기는 하지만, 성능을 우선하고 있다는 점이 다르다. 호환성을 중요하다면 CygWin을, 호환성을 약간 희생하고 좀 더 높은 성능을 필요로 한다면 MSYS이 적당하다. MSYS가 CygWin보다 설치가 간단하고 성능도 괜찮지만 여전히 CygWin이 필요한 .. 더보기
C++의 새로운 표준, C++0x에서 C++11으로 지난 8월 15일, C++0x가 드디어 ISO 회의에서 만장일치로 통과되었다. C++0x는 이제 C++11로 불려질 것이다. 언어 자체의 기능으로 가장 주목을 받는 것은 단연 rvalue reference와 람다 함수다. 표준 라이브러리에 새롭게 추가되는 기능들은 사실 boost에서 이미 지원하고 있었기 때문에 그렇게 커다란 차이를 느끼기는 힘들 것이다. 람다 함수는 특정 범위(scope)에서 이름 없는 함수로 동작하면서 람다 함수 내부에서 외부의 어떻게 변수를 사용할 수 있는지 명확하게 지정할 수 있지만([]), 기존의 함수자(functor)와 개념상으로 큰 차이는 없다. 따라서, C++11이 기존 C++ 사용자들에게 커다란 충격을 줄 부분은 단연코 rvalue reference다. 간단히 말해, rv.. 더보기
직선과 삼각형의 교차점 검사 공간에서 직선과 삼각형의 교차 여부를 조사하는 알고리즘을 이해하기 위해서는 먼저 무게 중심(barycentric coordicate)을 이해해야 한다. 즉, 삼각형이 3개의 버텍스 로 구성되어 있을 때, 내부의 점 은 으로 표현할 수 있으며, 은 의 좌표에 미치는 의 가중치를 나타낸다. 을 만족해야 한다. 따라서, 다음과 같이 정리할 수 있다. 여기서 는 로 바꿔 쓸 수 있으며, 광선 와 삼각형의 교차점을 구하는 것은 방정식 의 해를 구하는 것과 같다. 즉, 다음의 방정식으로 표현할 수 있다. 여기서 로 정의하면, 는 크라머(Cramer)의 공식에 의해 구할 수 있다. 위의 식은 다음과 같이 다시 정리할 수 있다. 최종적으로, 이것을 의사코드로 표현하면 다음과 같다. // o is ray's origin.. 더보기
예외를 전파하기 전에, 할당한 자원은 반드시 해당 개체에서 회수하라 에러에 대한 대책으로, 예외(exception)가 가지는 장점은 뚜렷하다. 기존의 함수 리턴값에 의존하는 구조로는 다루기 힘든 에러 처리도 예외를 사용하면 훨씬 구조적으로 처리할 수 있는 경우가 많다. 그러나, 제대로 된 예외 처리는 쉽지 않다. 예외에 신경쓰기 시작하면, 대체 어느 것이 예외에 안전한 코드인지, 그리고 예외를 처리하는 와중에도 발생 가능한 예외 때문에 상당히 골머리를 썩이게 된다. 기본 자료형 사이에서의 단순 연산은 예외를 일으키지 않지만, 문제는 사용자에 의해 생성된 자료형이다. 이들은 기본 자료형만으로 구성되어 있지 않기 때문에, 이런 자료형을 사용하는 도중 발생하는 예외는 프로그램 자료구조 일관성에 큰 영향을 미친다. 극단적으로 단순화해서 이야기한다면 힙에 관련된 연산은 언제나 예.. 더보기
쉐이더 아키텍처를 사용하는 OpenGL 프로그래밍에서의 텍스처 매핑 OpenGL에서, 텍스처 매핑(texture mapping)을 사용하는 방법은 고정 처리 파이프라인(fixed pipeline)을 사용하느냐, 쉐이더 파이프라인을 사용하느냐 여부에 따라 달라진다. OpenGL 2.0 이전의 고정 파이프라인 구조에서는 명시적인 glActiveTexture() 사용이 중요한데, 이것은 여러 장의 텍스처를 사용하는 방법은 멀티 텍스처링이 유일하기 때문이다. 반면, 쉐이더 아키텍처를 사용하는 OpenGL 2.0 이후의 구조에서는 생성된 텍스처 개체의 바인딩 대상이 되는 텍스처 유닛과 샘플링 방법만 필요하다. 생성된 텍스처 개체를 바인딩했다면, 쉐이더의 샘플러에게는 어떤 텍스처 유닛이 사용될 것인지 전달하면 된다. 그리고, 이 부분이 가장 중요한데, 상태 설정을 위해 바인딩 되는.. 더보기