1. Old. Old. Old style

C++:
  1. char buffer[1024];
  2. ...(기타 여러 코드들)...
  3. sock.recv(buffer, 1024);

혹시 위와 같은 스타일의 코드를 작성하고 있지는 않으신가요? 물론, 잘 작동하고 문제가 없는 코드일겁니다. 하지만, 여기엔 문제가 하나 있습니다. buffer는 배열이지 객체가 아닙니다. iterator도 없으며, 멤버함수도 없습니다. 불편할 뿐더러 위험합니다. 한번 볼까요?

C++:
  1. char buffer[1024];
  2. ...(기타 여러 코드들. 복잡해서 눈에 잘 안들어옴)...
  3. sock.recv(buffer, 4096); // 뭔가의 필요에 의해 고쳐졌군요.

와우. 망했습니다. 스택이 깨지면서 어떤 문제가 발생할지 감도 잡기 힘듭니다. 주로 보안사고가 이런 코드에서 많이 발생합니다. buffer overflow죠. 이런 류의 "실수"를 하지 않는다고 보장할 수 있을까요? 네. 이런걸 막기 위해 사람들은 이렇게 작업하기도 합니다.

C++:
  1. #define BUFFER_SIZE 1024
  2. char buffer[BUFFER_SIZE];
  3. ...(기타 여러 코드들. 복잡해서 진짜 눈에 잘 안들어옴)...
  4. sock.recv(buffer, BUFFER_SIZE);

별 문제 없어보입니다. 하지만, 버퍼의 크기가 각 위치마다 달라져야 한다면.. 그 수만큼 #define도 늘어날겁니다. enum을 쓰더라도 이건 매한가지죠.

그렇다면, 이런건 어떨까요.

C++:
  1. std::vector<char> buffer;
  2. buffer.resize(1024);
  3. sock.recv(&buffer[0], buffer.size());

훌륭하죠. 이제 C++답습니다. 하지만, buffer는 여전히 stack변수이며 이 부분이 실행될때마다 매번 새로 만들어질겁니다. 그리고, 매번 새로 만들어진다는건... 매번 할당자를 호출해야한다는 겁니다. (쉽게말해 new/malloc이 매번 호출됩니다. 재앙이죠.)

이걸 막기 위해선, 그렇죠. buffer를 재사용하면 됩니다. 하지만, 재사용시에는 언제나 멀티쓰레드 환경을 고민해야하는 상황이 다가옵니다. 후.

좀 더 C++다우면서, 배열과 같은 효과를 내는건 불가능할까요?


2. olleh! array!

C++:
  1. boost::array<char, 1024> buffer;
  2. sock.recv(&buffer[0], buffer.size());

네. 완벽하게 C++ container스러우면서, 배열의 역할을 수행하는 자료구조입니다. boost::array이죠! 이녀석의 내부구조는 다음과 같습니다.

C++:
  1. template<class T, int N>
  2. class array
  3. {
  4.     ...(생략)...
  5.     T elems[N];
  6. };

유일하게 갖고 있는 멤버변수는 elems. 배열입니다! 결국 배열을 선언한 것과 동일한 효과를 갖습니다. 여기까지 왔으면, 파직 하고 뭔가 옵니다.

array는 iterator, const_iterator, size(), begin(), end(), front(), back(), empty()등의 STL컨테이너라면, 다들 갖고 있는 형식과 함수들을 갖추고 있습니다. 그러면서도 []연산자를 지원하여 기존의 배열과 흡사하게 사용할 수 있지요. 이것이 시사하는 바는 생각보다 큽니다.

기존의 배열에 알고리즘을 적용해봅시다.

C++:
  1. char buffer[1024];
  2. ...(생략)...
  3. char* found = std::find(buffer, buffer+1024, 'c');

위와 같은 알고리즘을 적용할 경우, 1024라는 크기상수가 지속적으로 따라다닙니다. 또한, buffer를 vector나 다른 자료구조로 바꾸기라도 하면, 꽤 많은 수정을 가해야하지요. 하지만, boost::array를 사용한다면 다음과 같이 바뀝니다.

C++:
  1. // 편의를 위한 typedef. C++ 프로그래머의 친구죠. :)
  2. typedef boost::array<char, 1024> buffer_type;
  3. buffer_type buffer;
  4. buffer_type::iterator found =
  5.     std::find(buffer.begin(), buffer.end(), 'c');


3. 정리

사실, boost::array(TR1에 들어갔으니 이젠 tr1::array려나요.)는 굉장히 간단하고, 의미없게 느껴질 수 도 있습니다. 하지만, 과거의 배열은 원소들을 담는 컨테이너의 역할을 함에도 불구하고 STL스럽지 않다는 단점이 있었습니다. 자료구조를 다루는데 있어서, STL 컨테이너들과 굉장히 동떨어진 사용법은 코드의 일관성을 해치게 됩니다.

이런 면에서 볼 때, 배열과 동일한 구조/성능을 가지고 있으면서 STL 컨테이너와 유사한 인터페이스를 갖춘 array는 C++내에서 C의 유산에 의해 코드가 망가지는 것을 피할 수 있도록 해주는 상당히 중요한 도구입니다. :) 그리고, 200줄이 안되는 이 코드는 좋은 참고자료이기도 합니다. 시간 나시면 꼭 한번 읽어보시길. :)


A. References
boost::array의 문서

회사의 코드들이 상당히 계층적으로 묶여있는 상속관계... 즉, 결과와 관련된 모든 클래스는 ResultInterface라는 순수 가상 클래스(즉, 인터페이스)를 상속받고 있는 관계로 dynamic_cast를 if문으로 쭈욱 연결해서 해당 함수를 호출하는 코드가 일반적이었다.
Read the rest of this entry »

지난 3월에 C++ Standard Committee회의가 독일 베를린에서 있었다는군요. 이거 엄청난 뒷북이겠으나, 괄목할만한 것들이 들어있기에 언급하고 넘어가려고 합니다. (대체 이게 얼마만의 Development Note냐.. 반성좀 하자.)

일단, 소스는 Dr. Dobb's Journal의 C++ Department (formerly C/C++ User's Journal) 6월호(?)에 실린 Pete Becker씨의 Living by the Rules: Part II입니다. Pete Becker씨의 글은 참 읽기 편하고 즐거워요. :) C++ Standard Committee 멤버이고, C++ Standard의 Project Editor로 계신답니다. 지금 C++ Library Standard TR1에 대한 책을 쓰고 계시다는군요. 기대중. Read the rest of this entry »

일하는 중간에 컴파일러를 Microsoft Visual C++ Compiler에서 Intel C++ Compiler로 바꿔보면 어떨까라는 생각이 문득 들기에..

삽질을 해버렸습니다. 므흣.

먼저 stlport 4.6.2로 삽질을 했는데, 하다보니 어차피 5.0으로 옮길거 귀찮기도 하고 해서 stlport 5.0.1로 버젼을 바꾸고 빌드 시도.

boost에서 std::type_info를 못찾는다고 징징거리고, new.h를 인클루드 할 수 없다고 배째기에 코드를 곰곰히쳐다보았더랍니다.

문제는 Intel C++ Compiler가 MSVC 호환모드로 작동할때에는 Intel용 컴파일과 다른 식의 설정적용이 되어야 하는데 그게 안되어 있더군요. 훗. MSVC 호환모드면서 Intel C++ Compiler라면 처리를 다르게 해주어야 하는데 말이죠..

그래서 #if 문에 몇가지 조건문을 넣어주니 완벽하게 작동. 눈물을 흘리면서, 기뻐했더랍니다. 하하.

내친김에 WinMerge로 패치파일 만들어서 stlport팀에 보내주었더니 1시간 좀 지나서 바로 적용해주네요. 아이 기분 좋아라. >.<b

5.0.2에는 단 2줄이지만 까막군의 수정사항도 반영될듯. 에헤.

CodeBlocks는 오픈소스 크로스플랫폼 C++ IDE입니다.
그토록 갈구하던 녀석이군요. 으흑. ;ㅁ;

특이한 점이랄까.. 하는 것은 여러 C++ Compiler를 지원한다는 점입니다.

  • GCC (MingW / Linux GCC)
  • MSVC++
  • Digital Mars
  • Borland C++ 5.5
  • Open Watcom


지원하는 군요. 어차피 쓰는 것은 MSVC++과 GCC이긴 하겠지만요. 리눅스에서도 작동하고 윈도우에서도 작동합니다. 특히
윈도우 플랫폼에서는 MingW가 기본으로 포함된 버젼도 있군요. 키야앙!!! - MSVC++은 무료로 제공되는 컴파일러가
있지요.. 후후후.

사실 DevC++같은 툴은 모자란 점이 좀 많아서 불만이었는데, 이건 쓰기 편한점이 많은듯 하네요.

아직, auto-completion같은 기능이 좀 모자란 면이 보이긴 하지만, 해결되리라 생각하고...
디버깅기능도 살짝 모자랍니다. local변수 보기같은... (Watch만 되는 것 같더군요)

MSVC++ 프로젝트 임포트도 지원하고. (버그는 좀 있답니다..)

사실 STL/Boost의 auto-completion만 잘 지원되주기만 해도.. 으흐흐.

CodeBlock의 완성도가 높아진다면, 굳이 Visual C++을 이용할 이유가 사라질 것 같기도 합니다. :)