Subscribe: 김윤수의 이상계를 꿈꾸며
http://yesarang.tistory.com/rss/
Added By: Feedage Forager Feedage Grade A rated
Language:
Tags:
Rate this Feed
Rate this feedRate this feedRate this feedRate this feedRate this feed
Rate this feed 1 starRate this feed 2 starRate this feed 3 starRate this feed 4 starRate this feed 5 star

Comments (0)

Feed Details and Statistics Feed Statistics
Preview: 김윤수의 이상계를 꿈꾸며

김윤수의 이상계를 꿈꾸며



이상계는 이쪽에 속해있지 않고 저쪽에 속해 있다. 이쪽에 사는 우리는 이쪽에 머무르지 않고 저쪽을 꿈꾸며 살아야 한다. 여기 오는 모든이들이 저쪽의 충만함을 이쪽에서의 매일의 삶에 경험



Published: Sun, 17 Dec 2017 00:03:38 -0800

 



C++ 최근 소식

Sun, 07 Jul 2013 08:44:26 -0700

정말 오랜만의 포스팅입니다.

몇 가지 최근 C++ 소식 알려 드립니다.

1. C++14 Committee Draft가 벌써 나왔습니다. 다음은 PDF파일 다운받을 수 있는 링크입니다.

2. Herb Sutter씨가 최근 Microsoft channel 9에서 "The Future of C++"라고 강연한 내용에서도 C++14 feature가 간략하게 소개되고 있네요.

3. Clang의 C++14 구현 상황입니다.

4. g++의 C++14 구현 상황입니다.

5. Visual Studio C++14 구현 계획입니다. MS는 C++11과 C++14을 한 묶음의 일로 보고 작업 중이라는군요.

6. 참고로 http://isocpp.org/ 는 얼마전에 만들어진 C++ 언어 포털이라고 할 수 있습니다.


(image) (image) (image)
src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/378&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true">



C++11의 rvalue reference 흉내내기

Sun, 01 Jul 2012 06:40:36 -0700

C++11의 큰 특징 중의 하나로 rvalue reference라는 것이 도입되었습니다. reference라는 것이 기본적으로 lvalue로 작동할 수 있는 것인데 rvalue reference라는 개념이라는 게 있을 수가 있나 하는 생각이 들지만, 불필요한 임시객체 생성 및 삭제로 인한 성능 저하를 막기 위해 도입된 것이라 할 수 있습니다. 일명 move semantic과 perfect forwarding을 위한 것이라고 합니다.성능이라는 단어가 나오면 보통 C++ 프로그래머들은 관심을 갖기 마련이고, 그런 좋은 것이 있다면 빨리 쓰고 싶기도 할 터인데요, C++11을 일부 지원하는 기능을 컴파일러가 시장에 나오긴 했더라도 자신이 속한 프로젝트에서는 정책상 C++11 기능을 사용하지 못하게 해 놓을 수도 있을 것입니다. 그렇다고 이 좋은 기능을 그냥 보고 넘어갈 수도 없는 노릇이겠지요.그래서 한 번 생각해 봤습니다. rvalue reference를 흉내낼 수는 없을까하구요. 한 동안 고민하고 있었는데, 어느 순간 갑자기 아이디어가 떠오르더군요. 떠오른 생각을 빠르게 한 번 옮겨 봤습니다.#include using namespace std;namespace buffer {// 테스트용 클래스class Foo {public:    Foo() {        cout << __PRETTY_FUNCTION__ << endl;    }    ~Foo() {        cout << __PRETTY_FUNCTION__ << endl;    }};class BufferRvRef;class Buffer {public:    // 아래 template Move 함수의 일반적 정의를 위한 보조 타입    typedef BufferRvRef RvRef;    Buffer() : buf_(new Foo()), id_(id) {        cout << __PRETTY_FUNCTION__ << " - " << id_ << endl;        ++id;    }    // move constructor    // rvalue reference를 받는 경우를 흉내내서 move semantic     // 구현    Buffer(const RvRef& rvref);    ~Buffer() {        cout << __PRETTY_FUNCTION__ << " - " << id_ << endl;        delete buf_;    }private:    // move semantic 구현. copy construction시 const 객체를     // 받으므로 const 멤버 함수로 정의함    Foo* release() const {        cout << __PRETTY_FUNCTION__ << " - " << id_ << endl;        Foo* ret = buf_;        buf_ = 0;        return ret;    }    // release() 함수에서 buf_ 조작을 위해서 mutable 붙임    mutable Foo* buf_;    // 화면 출력 메시지에서 각 객체 구분 용도. 실제 클래스라면 불필요    int id_;    // BufferRvRef가 release()를 호출할 수 있도록 하기 위해     // friend로 선언    friend class BufferRvRef;    static int id;};int Buffer::id = 0;// Buffer 내부 데이터를 move 시키기 위한 임시 저장소 역할class BufferRvRef {public:    // const Buffer 객체를 임시로 저장함    explicit BufferRvRef(const Buffer& buf)         : buf_(buf.release()), id_(id) {        cout << __PRETTY_FUNCTION__ << " - " << id_ << endl;        ++id;    }    BufferRvRef(const BufferRvRef& other)         : buf_(other.release()), id_(id) {        cout << __PRETTY_FUNCTION__ << " - " << id_ << endl;        ++id;    }    // move semantic 구현    Foo* release() const {        cout << __PRETTY_FUNCTION__ << " - " << id_ << endl;    &[...]



C++11 atomic 객체 맛보기

Sun, 01 Jul 2012 01:29:01 -0700

C++11 atomic을 이용해서 프로그래밍할 때 어떻게 해야 하는지 맛 보기 위해 간단한 예제를 작성해 봤습니다. multiple thread에서 공유 integer 변수를 loop 한번 당 매번 1씩 경쟁적으로 증가시키는 간단한 프로그램입니다.일반 integer 변수와 atomic integer 변수로 비교해 보았고, 일반 integer 변수의 경우 역시 예상대로 정확한 결과가 나오지 않았고, atomic integer 변수는 정확한 결과가 나왔습니다.또, 일반 integer 변수는 상당히 빠르게 수행되지만 atomic integer 변수는 상당히 느리다는 것을 확인할 수 있었습니다.테스트 프로그램은 다음과 같습니다. C++11 프로그램인 만큼 몇 가지 C++11 스타일을 적용했습니다#include #include #include // C++11 가 있으나 버그가 있어 사용하지 못하고 // boost::thread 사용#include using namespace std;using boost::thread;enum {    NTHREADS = 8,      // Core i7 Desktop이라 8로 설정    NRUN = 10000000,    NLOOP = NRUN * 10};// atomic integer type. atomic라고도 할 수 있음. // atomic하게 증가됨atomic_int an{0};int n{0};void increment_atomic(int id, int nloop) {    cout << __PRETTY_FUNCTION__          << "(" << id << ") starts" << endl;    while (nloop-- > 0) {        // relaxed memory ordering. // 단순 카운트인 경우에 충분        an.fetch_add(1, memory_order_relaxed);        // an.fetch_add(1, memory_order_seq_cst);        // or ++an; 일반 integer처럼 prefix ++ 지원 // 이 때 memory ordering은 memory_order_seq_cst        if (nloop % NRUN == 0)            cout << __PRETTY_FUNCTION__                  << "(" << id << ") running..." << endl;    }    cout << __PRETTY_FUNCTION__          << "(" << id << ") exits" << endl;}void increment_int(int id, int nloop) {    cout << __PRETTY_FUNCTION__          << "(" << id << ") starts" << endl;    while (nloop-- > 0) {        ++n;        if (nloop % NRUN == 0)            cout << __PRETTY_FUNCTION__                  << "(" << id << ") running..." << endl;    }    cout << __PRETTY_FUNCTION__          << "(" << id << ") exits" << endl;}void test_func(void (*incr)(int, int), void (*print)()) {    vector thrs{};    cout << "Creating threads" << endl;    for (int i = 0; i < NTHREADS; ++i) {        // 개선된 push_back()이라 할 수 있는         // emplace_back() 활용        thrs.emplace_back(thread(incr, i, NLOOP));    }    cout << "Waiting for all threads to terminate" << endl;    // lambda 함수 사용    for_each(thrs.begin(), thrs.end(), [](thread& thr) {        thr.join();    });    print();}void usage() {    cout << "Usage:" << endl;    cout << "test-atomic atomic|int" << endl;}int main(int argc, char* argv[]) {    if (argc == 2)     {        string type{argv[1]};        if (ty[...]



C++11 기능 소개: 중첩 '>' 문제 해결

Mon, 09 Apr 2012 20:30:00 -0700

여러 말로 설명하기 보다 관련 예제부터 한 번 보겠습니다.map> heroChronicles;C++98에서는 위 코드가 컴파일되지 않습니다. 왜냐하면 “>>”이 연속된 ‘>’으로 인식되는 것이 아니라 구문 분석 시작 전 어휘 분석 단계(lexical analysis)에서 최대 흡수(Maximal munch) 규칙에 따라  “>>” 토큰으로 인식되고 이는 다시 문법 단계에서 “>>” 연산자로 인식되고, ">>" 연산자 좌우로 int, heroChronicles 같은 토큰들이 있는 것으로 인식되기 때문입니다. 템플릿 초심자들이 많이 저지르는 실수이죠. 그래서 C++98에서는 다음과 같이 작성해야 했습니다.map > heroChronicles;이 뿐 아니라 새로운 형태의 형변환 연산자도 비슷한 문제가 있습니다.static_cast>(ld);    // static_cast>(ld)); 로 해석>>= 및 >= 도 비슷한 문제가 발생할 수 있습니다.void func(List= default_val1);   // 원래 의도는 List lb = default_val1이나  // List<(B >= default_val1)); 으로 해석 void func(List>= default_val2);   // 원래 의도는 List> llb = default_val2이나 // List>= default_val2)); 으로 해석템플릿이 많이 사용되면 많이 사용될 수록 이런 코드는 더 큰 문제가 될 것입니다.애초에 C++98에서 이런 문제가 발생했던 것은 컴파일러가 이론적으로 어휘분석, 문법분석, 형식체크와 같이 몇 단계를 거쳐 처리하므로 이 문제를 해결하기 위해서는 어휘 분석 단계가 문법 분석 단계와 협력해야 하는 문제가 발생하게 되기 때문이었습니다. 결국 컴파일러 구현자들을 위한 결정이었던 것이죠.그런데 시중에 출시된 C++ 컴파일러들이 이 문제를 인식하고 친철한 에러 메시지를 출력하고 있다는 것이 표준화를 진행하는 동안 밝혀졌습니다.예를 들어, g++에서는 다음과 같은 에러 메시지를 출력하고 있었습니다.error: ‘>>’ should be ‘> >’ within a nested template argument list이 정도로 이미 컴파일러들이 이 문제를 나름대로 인식하고 해결하고 있었기 때문에 C++11에서는 어휘 분석 단계와 문법 분석 단계가 협력하여 문제를 해결하도록 표준에 명시하기에 이르렀습니다. 기본적으로 다음과 같은 규칙을 따르도록 되어 있습니다.왼쪽 ‘<’ 이 ‘>’과 서로 매치가 되어 있지 않은 동안에는 >> 토큰은 오른쪽 shift 연산자가 아닌 두 개의 연속된 ‘>’로 인식되어야 한다.위와 같은 규칙은 어휘 분석 단계와 문법 분석 단계가 긴밀하게 협력할 필요 없이 문법 분석 단계에서 간단한 검사만 하면 구현할 수 있을 정도이므로 컴파일러 구현에도 큰 문제가 되지는 않을 것입니다.항상 그렇듯 이 규칙에도 예외가 있습니다.다음 예제를 보시죠.Y>1>> x4;코드를 보고 예측해 보건데 프로그래머는 6>>1의 결과값을 X 템플릿의 인자로 주고 싶었을 것입니다. 즉, 다음과 같은 의미였겠죠.Y>1)>> x4;이런 코드가 문제 없이 컴파일되도록 하기 위해서는 괄호 안에서는 위와 같은 규칙이 적용되지 않도록 해야하므로 다음과 같이 예외조항을 두어야 할 것입니다. 왼쪽 ‘<’ 이 ‘>’과 서로 매치가 되어 있지 않은 동안에는 >> 토큰은 오른쪽 shift 연산자가 아닌 두 개의 연속된 ‘>’로 인식되어야 한다. 단, 괄호쌍이나 대괄호쌍에 있는 >>는 예외이다.이 규칙이 C++11에서 정하고 있는 것과 정[...]



C++11 기능 소개: 상속생성자(Inheriting Constructor)

Wed, 28 Mar 2012 06:51:13 -0700

상속생성자란 기본클래스에 정의된 생성자를 상속받는 클래스에서 상속받을 수 있도록 하는 기능이다.상속생성자는 컴파일러가 기본생성자와 복사생성자를 생성하는 규칙 때문에 발생하는 문제점을 해결하기 위한 기능이므로 우선 이 규칙을 이해할 필요가 있다. C++ 컴파일러는 프로그래머가 생성자를 정의하지 않으면 기본 생성자 및 복사생성자를 알아서 생성한다. 예를 들어, class B {  int v_;public:  int get();  void set(int v);};B b;와 같은 코드가 아무런 문제 없이 컴파일되는 이유는 컴파일러가 기본생성자를 생성해 주기 때문이다. 그런데 B를 쓰다 보면 기본생성자에 의해 초기화되지 않은 멤버 변수 값 때문에 문제가 생기는 경우가 있기 마련이다. 예를 들어, void f();B b;f(b.get());와 같은 코드를 실행할 경우 b.v_에 담긴 쓰레기 값 때문에 문제가 발생할 수 있을 것이다. 이런 문제를 발견했을 때 상식있는 프로그래머라면 다음과 같이 생성자를 추가할 것이다.class B {  int v_;public:  B(int v) : v_(v) {}  int get();  void set(int v);};B b;그러면 당장 다음과 같은 에러가 발생하게 된다.error C2512: 'B' : 사용할 수 있는 적절한 기본 생성자가 없습니다.그렇다. 프로그래머가 기본생성자가 아닌 생성자를 하나라도 추가하면 컴파일러가 기본생성자를 생성하지 않는 것이다. 이제 프로그래머가 직접 기본생성자를 작성해야 한다.class B {  int v_;public:  B() : B(0) {} // C++11의 위임생성자 기능 활용  B(int v) : v_(v) {}  int get();  void set(int v);};그런데 만약 B로부터 상속 받은 D라는 클래스가 있었다고 생각해 보자.class D : public B {public:  void compute();};B::B(int)가 추가된 이유를 이해하는 프로그래머라면 D를 사용할 때 다음과 같이 생성시 초기값을 제대로 지정하려고 할 것이다.D d(10);그렇지만 위 코드는 컴파일 에러를 발생시킨다. 왜냐하면 D::D(int)는 애초에 정의되어 있지 않기 때문이다. 결국 D를 작성한 프로그래머는 다음과 같이 D::D(int)를 추가해야 한다.class D : public B {public:  D(int v) : B(v) {}  void compute();};D d(10);그렇다면 다음 코드는 어떨까? D d2;d2.set(10);D::D(int)가 없었기 때문에 충분히 여러 차례 사용될만한 코드 패턴일 것이다. 그렇지만 D를 작성한 프로그래머가 D::D(int)를 추가한 순간 위와 같은 코드 패턴들은 모두 컴파일 에러를 일으키게 된다. D 클래스를 작성한 프로그래머와 위 코드를 작성한 프로그래머가 같다면 별 문제 없겠지만 다르다면 사무실 어느 구석에선가 “악~”하고 소리가 날 일이다. 결국 D는 다음과 같이 작성되어야 한다.class D : public B {public:  D() : B() {}  D(int v) : B(v) {}  void compute();};D d(10);D d2;d2.set(10);창조적 귀차니즘이 있는 프로그래머라면 이쯤에서 의문이 하나 생긴다. “왜 이렇게 불편하게 해 놓았지? 애초에 D가 B의 생성자들을 다 물려받으면 되잖아. 상속에는 생성자 상속까지 포함되어야 하는 거 아닌가?”상속생성자는 이런 의문에서 출발한 기능이다. 위 질문에 대한 해답으로 상속시에 생성자를 모두 물려받는 것으로 정하면 되지 않을까 하는 생각이 제일 먼저 들 것이다. 그렇지만 이렇게 상속의 의미를 수정할 경우 기존에 이미 존재하던 수많은 코드들이 컴파일되지 않거나 컴파일은 되는데 예상치 못한 실행시 에러가 발생할 수 있다. 언어가 발전함에 있어 이런 급작스런 변화는 거의 불가능하다고 볼 수 있다. 기존 코드를 모두 [...]



C++ 이야기: 예외 처리와 관련된 고전 글 번역

Wed, 30 Jun 2010 07:14:24 -0700

다음 글은 예외 처리 기능이 C++에 도입된지 얼마되지 않아 C++ 커뮤니티에서 예외를 사용할 때 유의해야할 점에 대해 잘 깨닫지 못하고 있을 때, 예외에 대한 새로운 통찰력을 제공해 주고, 예외 처리를 위한 다양한 기법들의 시발점이 된 고전 Tom Cargill 의 Exception handling: a false sense of security 를 번역한 것입니다. 원문은 이 링크에서 보실 수 있고, 원문에서 약간 코드 상 잘못된 부분들(template 키워드 뒤에 가 따라오지 않는다던지 literal string 이 ""..."" 과 같이 되어 있다던지)을 수정하고 영문과 한글을 대조하면서 보실 수 있도록 했습니다. C++ 로 프로그래밍 하시는 분이라면 필독해야 할 글이라고 할 수 있습니다. 그렇지만 이 글만 읽지 마시고, 2009/09/25 - [S/W개발/C++ 이야기] - C++ 이야기 서른한번째: 왜 예외를 쓰는 게 좋을까요? 와 비교해서 읽어 보시면 예외의 장점과 단점을 어느 정도 파악하실 수 있을 거라 생각합니다. 이 글만 읽으시면 마치 예외가 문제를 더 많이 일으키는 것 같지만, 이 글이 문제점을 제기한 이후에 많은 분들이 예외 안전성을 확보할 수 있는 프로그래밍 기법들을 알아내어 그 방법대로 프로그래밍하면 별 문제 될것이 없습니다. 다만, 이런 프로그래밍 기법을 공부하는데 어느 정도 시간이 필요한 것이 더 문제겠지요. 또 이 글만 읽고 예외는 절대 쓰면 안된다는 결론에 빠지지 않기를 바랍니다. EXCEPTION HANDLING: A FALSE SENSE OF SECURITY 예외 처리: 잘못된 안정감 Tom Cargill 저 김윤수 역 This article first appeared in C++ Report, Volume 6, Number 9, November-December 1994. 이 글은 C++ Report, 6권, 1994년 11월, 12월, 9번째판에 처음 게제됐습니다. I suspect that most members of the C++ community vastly underestimate the skills needed to program with exceptions and therefore underestimate the true costs of their use. The popular belief is that exceptions provide a straightforward mechanism for adding reliable error handling to our programs. On the contrary, I see exceptions as a mechanism that may cause more ills than it cures. Without extraordinary care, the addition of exceptions to most software is likely to diminish overall reliability and impede the software development process. 저는 C++ 사용자 대부분이 예외를 사용하는 프로그램을 작성하는 데 필요한 노련미를 너무 무시하고 있지 않는지, 그럼으로 인해 예외를 사용할 때, 진정 치뤄야할 대가를 무시하고 있지는 않은지 염려스럽습니다. 오히려 대부분은 예외를 사용하면 바로 신뢰성 있는 에러 처리가 가능하다고 믿는 것 같습니다. 저는, 이와는 반대로, 예외를 사용하면 해결되는 문제보다는 새롭게 발생하는 문제가 많다고 생각합니다. 정말 정말 조심하지 않고 예외를 사용하면, 소프트웨어의 전반적인 신뢰성이 훼손되고 소프트웨어 개발 과정이 지연될 가능성이 높아집니다. This "extraordinary care" demanded by exceptions originates in the subtle interactions among language features that can arise in exception handling. Counter-intuitively, the hard part of coding exceptions is not the explicit throws and catches. The really hard part of using exceptions is to write all the intervening code in such a way that an arbitrary exception can propagate from its throw site to its handler, arriving safely and without damaging other parts of the program along the way. 이렇게 정말 정말 조심해야 하는 이유는 예외 처리 과정에서 발생하는 언어의 다양한 특징들간 미묘한 상호 작용때문입니다. 언뜻 보기와는 달리 예외를 사용[...]



C++ 이야기 서른두번째: 예외가 성능에 미치는 영향

Sun, 20 Jun 2010 08:01:54 -0700

2009/09/25 - [S/W개발/C++ 이야기] - C++ 이야기 서른한번째: 왜 예외를 쓰는 게 좋을까요? 에서 왜 예외를 쓰는 것이 좋은지에 대해 얘기를 해 봤습니다. 정리해서 말씀드리자면 결함내성 특성(fault-tolerant)을 가진 소프트웨어를 작성하기 쉽게 해주기 때문에 예외를 쓰는 것이 좋다라고 말씀드렸습니다. 그런데 폴리비님께서 다음과 같은 댓글을 남겨 주셨습니다. 예외 처리기능이 C++에 들어가서 좋지만, 속도 저하가 약간 있어서 꺼리는 경우도 있어요. 스트롭 할아버지는 별로 속도 저하 없으니 꼭 쓰라고 하지만 RTTI처럼 속도 때문에 꺼려지는 점이 있긴 하죠! STL도 vector에 대해 at 메소드는 예외처리를 하지만, 완전 동일한 기능인 [] 연산자에서는 예외처리를 하지만, 많은 반복 예상되는 단순한 코드같은 경우 예외 처리가 꼭 필요하지는 않으면서도 예외 처리를 할 경우 성능을 떨어뜨리는 경우도 있습니다. 예외 처리 기능을 활용하면 성능을 떨어뜨리니 무조건 쓰는 건 좋지 않다라는 말씀이겠죠. 이 댓글을 보고 예외가 성능에 도대체 어느 정도나 영향을 미치는지 알아보고 싶어서 실험을 해 봤습니다. 예외 처리가 성능에 미치는 영향을 측정하기 위해서는 어떻게 실험해야할까요? 예외 처리 기능을 사용하는 프로그램과 사용하지 않는 프로그램의 실행 시간을 비교해봐야겠다는 생각이 자연스럽게 떠오릅니다. 그렇지만 이 둘만 비교해서는 예외가 성능에 미치는 영향을 정확히 파악할 수 없을 것입니다. 왜냐하면, 단순히 try/catch 문을 사용했을 경우와 실제로 예외가 발생한 경우에 발생하는 overhead가 다를 것이기 때문입니다. try/catch 문만을 사용했을 경우에는 예외 처리를 위한 준비과정만 부가적인 overhead가 되겠지만, 예외가 실제로 발생한 경우에는 예외를 처리하는 과정(대표적으로 stack unwinding)이 overhead가 될 것이기 때문입니다. 예외가 발생하는 경우도 호출 깊이(call depth)가 어느 정도이냐에 따라 overhead가 달라질 수 있을 것이므로 호출 깊이도 달리 하면서 실험할 필요가 있을 것입니다. 마지막으로 호출 깊이가 깊어지는 경우 중간에 예외 처리기가 여러번 중첩될 수도 있고, 이런 예외 처리기에서 예외를 재발생시키거나(rethrow) 다른 예외로 매핑하는 경우도 있을 것입니다. 따라서 이러한 경우도 분리해서 테스트할 필요가 있을 것입니다. 정리하자면 다음 네 가지 경우에 대해 호출 깊이를 달리하여 테스트하면 어느 정도 예외가 성능에 미치는 영향에 대해 윤곽을 잡을 수 있을 것 같습니다. 1. 예외 처리를 사용하지 않는 프로그램 2. 예외 처리를 사용하나 예외를 발생시키지 않는 프로그램 3. 예외 처리를 사용하고 예외를 발생시키나 재발생시키지는 않는 프로그램 4. 예외 처리를 사용하고 예외를 발생시키며 재발생시키기도 하는 프로그램 호출 깊이를 달리하는 것은 동일한 함수를 재귀 호출하는 회수를 달리하면 될 것입니다. 이 네 가지 경우를 다음과 같이 별도의 함수로 작성하였습니다. 먼저, 1. 예외 처리를 사용하지 않는 프로그램입니다. void NoTry(long long& r, int& rcnt) { shared_ptr p(new Foo()); r += (rand() % 100); if (--rcnt) NoTry(r, rcnt); } Foo 라는 클래스는 class Foo {}; 라고 비어 있는 클래스로 정의했습니다. rcnt 는 호출 깊이를 조절하기 위한 변수로 0이 되면 더 이상 재귀적으로 호출하[...]



최근 C++ 소식

Thu, 29 Apr 2010 05:58:13 -0700

1. C++0x Final Committee Draft(FCD)가 릴리즈됐습니다: Draft는 여기서 다운받을 수 있습니다. 표준화 과정 중에 논의된 내용들을 더 자세히 알고 싶으시면 이 링크를 보시면 됩니다. Draft는 무려 1310페이지에 달합니다. 읽어보실 분은 미리 각오하시고 읽어 보시는 게 나을 것 같습니다. ^^ 2. C++0x FCD를 읽고 comment 할 것들이 있다면 여기에 가서 comment를 남기시면 됩니다. 이제 final draft인 상태이기 때문에 주로 wording에 관련된 comment를 받아들이겠죠? 새로운 feature 추가하자 그러면 아마 받아들이지 못하겠죠. C++에 새로운 feature 를 추가하고 싶다면 여기를 한 번 보시고 페이지 관리자에게 메일 보내보시면 될 듯(저도 보내보진 않았어요). 3. Visual Studio 2010에 포함된 VC++이 지원하는 C++0x feature 구현 상태는 여기에서 보시면 됩니다. 4. GCC에서 지원하는 C++0x feature 구현 상태는 여기에서 보시면 됩니다. 5. 각 컴파일러의 C++0x feature 구현 상태는 여기에 정리되어 있네요. 6. C++ & Beyond 2010 Event가 열린답니다. 유명한 C++ 책 저자인 Herb Sutter, Scott Meyers , Andrei Alexandrescu 이 세 분이 주축이 돼서 진행하는 이벤트인가 보네요. 60명만 참가할 수 있답니다. 관심있으신 분은 여기서 등록하시구요. 누군가 저를 스폰서 해 주실 분이 계시다면 저도 가보고 싶은데 말입니다. ㅠ.ㅠ src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/370&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true"> [...]



C++ 이야기 서른한번째: 왜 예외를 쓰는 게 좋을까요?

Fri, 25 Sep 2009 07:59:16 -0700

If you're an English speaker, please follow this link 이글의 최신본은 항상 여기에 있습니다. 최신본은 코드에 syntax highlighting도 되어 있고, 철자법도 맞추고 부가정보도 계속 업데이트 하고 있습니다. 여러분은 서브루틴에 에러가 발생했다는 걸 알려주려 할 때 C++ 예외를 사용하시나요? 쓰시지 않는다면, 왠가요? 에러를 나타내는 특별한 에러 코드를 되돌려주면 되기 때문에 전혀 사용할 필요가 없다라고 답변하실지도 모르겠습니다. 사용하신다면, 왠가요? 이 질문에 대해서는 다른 방법이 있나요?라고 오히려 반문하시는 분이 있을지도 모르겠네요. C++에 예외가 도입된 이유를 밝하기 위해 이 글을 작성하게 됐습니다. 이 설명을 통해 위에 두 부류의 분들 모두 예외에 대해 더 잘 이해하게 되고, 예외를 이용하여 더 좋은 코드를 작성하는데 도움이 되시리라 생각합니다. C++에 왜 예외에 도입되었다고 생각하세요? 왜 아직도 Java나 C#같은 언어가 C++의 예외를 물려 받았다고 생각하세요? 그런데는 틀림없이 어떤 이유가 있을 것입니다. 그 이유는 바로 결함내성(fault-tolerant) 소프트웨어를 쉽게 작성하도록 하기 위한 것입니다. C/C++ 같이 상태를 갖는 프로그래밍 언어에서 에러 처리를 한 후에도 일관성있는 상태를 유지해야 한다는 건 결함내성을 달성하는데 있어 정말 까다로운 문제입니다. 예를 들어, 다음과 같이 어떤 파일을 열고 데이터를 읽어들이는 짤막한 C 코드를 생각해 보기로 하겠습니다. char* OpenAndRead(char* fn, char* mode) { FILE* fp = fopen(fn, mode); char *buf = malloc(BUF_SZ); fgets(buf, BUF_SZ, fp); return buf; } OpenAndRead()의 목적이 워낙 간단하고 분명하니, 그 구현도 무척이나 간단하고 읽기도 쉽고 이해하기도 쉽습니다. 위 코드는 모든 서브루틴이 잘 수행된다면 잘 작동할 것입니다. 그렇지만 'fn' 파일이 없거나 파일에 대한 접근 권한이 없다면 어떻게 될까요? malloc() 이나 fgets() 이 실패하면 어떻게 될까요? 위 코드를 결함내성이 있게 만들려면 각 서브루틴 호출 후에 에러가 발생했는지 확인해보고, 에러가 발생했다면 어떤 행동을 취해야할 것인지 결정해야 합니다. 그 취해야할 행동이 여기서는 단순히 에러 메시지를 출력하고 획득했던 자원들을 해제하고, -1 을 리턴하는 걸로 가정해 보겠습니다. 그렇다면 코드를 다음과 같이 수정할 수 있겠지요. int OpenAndRead(char* fn, char* mode, char** data) { *data = NULL; char* buf = NULL; FILE* fp = fopen(fn, mode); if (!fp) { printf("Can't open %s\n", fn); return -1; } buf = malloc(BUF_SZ); if (!buf) { printf("Can't allocate memory for data\n"); fclose(fp); return -1; } if (!fgets(buf, BUF_SZ, fp)) { printf("Can't read data from %s\n", fn); free(buf); fclose(fp); return -1; } *data = buf; return 0; } 두 개의 코드를 비교해 보니 느낌이 어떠세요? 두번째 버전은 주 알고리즘을 처리하는 부분과 에러를 처리하는 부분이 막 섞여 있어서 읽기도 힘들고 이해도 힘들어졌습니다. 게다가 라인수도 많아져서 일을 더 많이해야하네요. 예외를 사용하면 이런 문제가 발생하지 않습니다. 한 번 fopen(), malloc(), fgets() 이 FileDoesNotExist, FileNotAccessible, MemoryExhausted, EndOfFile 라는 예외를 발생시킨다고 가정해 보겠습니다. 그렇다면 다음과 같이 코드를 변화시킬 수 있을 것입니다. int OpenAndRead(char* fn, char* mode, char** data) { *data = NULL; char* [...]



위키 업데이트 상황

Tue, 22 Sep 2009 07:27:56 -0700

얼마전에 제가 블로그 글들 옮깁니다라는 글에서 소프트웨어 개발 관련 글들을 위키로  차례 차례 옮길 것이라고 공지를 드렸습니다. 그 이후에 짬이 나는 대로 옮기고 있는데, 블로그와 위키와의 차이점 때문에 그것도 그리 쉬운 것만은 아니네요. 일일이 하나씩 옮겨야 하니... 암튼 지금까지는 13개의 글을 옮겼습니다. auto_ptr 템플릿 클래스 소개(Korean) auto_ptr 의 두 얼굴(Korean) auto_ptr을 표준 컨테이너에 담지 말라(Korean) new와 delete(Korean) 기본기 다지기, bool type에 관하여(Korean) 기본기 다지기, explicit 키워드(Korean) 객체 자신을 가리키는 변수가 this 포인터인 이유는?(Korean) 임시 객체는 임시 객체일 뿐 No.1(Korean) 임시 객체는 임시 객체일 뿐 No.2(Korean) 임시 객체가 충분히 임시스럽기 위하여(Korean) 내 객체 복사하지마!(Korean) TR1 History(Korean) 어떻게 옮기고 있는지 궁금하신 분들은 한 번 들러보시기 바랍니다. 글 옮기는 거 외에도 한번 Why Exceptions?라는 제목으로 C++ exception을 쓰면 어떤 점이 좋은지에 대해 영어로 글을 써 봤습니다. 영어 잘 한다고 자랑하려는 건 아니구요(어차피 잘하지도 못하지만), 국내에만 머무르는 사람이 되지 않기 위해 영어로 작성해 보고 있습니다. 영어에 자신 있으신 분들은 여기에 한글 번역된 것을 올리기 전에 먼저 읽어 보시고 Comment 주시면 감사하겠습니다. 위키 주소는 http://opensw.wikidot.com 입니다. 많은 관심과 격려 부탁드립니다. ^^ src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/367&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true"> [...]



미투데이 대 트위터

Sat, 12 Sep 2009 20:12:30 -0700

미투데이와 트위터의 차이점: 미투데이는 초기부터 API를 써서 3rd party 응용을 위한 환경을 조성하긴 했지만 twitter 만큼은 open 하지 못했다. 왜냐면 traffic을 외부로 잘 넘겨주지 않는 내부완결형 구조 특성이 있다.(2tw 미투데이 트위터 차이점)2009-09-13 11:12:35 트위터는 140자 제한마저 외부 서비스를 활성화하는데 사용하고 있으나 미투데이는 링크를 표현하기 위한 별도의 방법을 정의했다. 이 때문에 미투데이가 풍부한 내용을 담을 수 있다는 장점이 있지만 에코시스템 창출에는 트위터가 나은 것 같다(2tw 미투데이 트위터 차이점)2009-09-13 11:15:58 물론 미투데이가 훨씬 우리나라 사람들 스타일에 맞는 것 같긴 하다.(2tw 미투데이 트위터 차이점)2009-09-13 11:16:59 그리고, 사진이랑 비디오를 flickr, youtube에 upload 하긴 하지만 in place로 보여주는 점 등이 그 예이다. 3rd party service가 활성화되기 위한 필요 조건이 traffic 분산이 아닐까 생각해 본다.(2tw 미투데이 트위터 차이점)2009-09-13 11:23:23 미투데이는 이제 인기를 끌기 시작했고, 트위터는 이미 사용자가 폭발한 상태이니 지금 시점에서 직접 비교하긴 힘들지만 나중에 어떻게 될까 상당히 궁금해지는 대목이다.(2tw 미투데이 트위터 차이점)2009-09-13 11:30:06 미투데이가 훌륭한 점 중에 하나는 태그가 따로 있다는 것이다. 짧은 글들이라도 모이면 상당히 중요한 정보가 될 수 있는 것인데, 태그가 그 역할을 충실히 해주고 있다.(2tw 미투데이 트위터 차이점)2009-09-13 11:32:24 트위터도 해쉬태그가 있지만 해쉬태그는 영어밖에 안된다는 문제가 있고, 해쉬태그 여러개 주면 글 쓸 공간이 금방 부족해져 버린다. 다른 사람 글에 대해 핑백으로 링크를 달 수 있는 것도 좋은 점 중의 하나이다.(2tw 미투데이 트위터 차이점)2009-09-13 11:35:02 트위터에서는 다른 사람 글도 보이고 자기 생각도 보이고 싶더라도 공간이 부족해서 그렇게 하질 못한다. 결국 원문을 편집하거나 자기 생각은 거의 없이 그냥 RT를 하게 되는 경우가 종종 있다.(2tw 미투데이 트위터 차이점)2009-09-13 11:36:43 다분히 유명인 위주로 다른 사람들은 그저 정보를 확산시키는 매개체로 작용할 가능성이 충분히 있다는 얘기다. 각 개개인의 개성은 몰살되고, 마케팅을 위한 채널 정도로만 악용될 가능성이 충분히 있다.(2tw 미투데이 트위터 차이점)2009-09-13 11:38:16 트위터에서는 친구라는 개념이 없고 팔로워라는 개념이 있는데, 팔로워는 미투데이의 구독개념과 비슷하다고 볼 수 있다. 친구만큼 깊은 관계를 맺고 싶진 않지만, 그 사람이 생성하는 정보에 대해서는 관심이 있다라는 정도라고 할 수 있다.(2tw 미투데이 트위터 차이점)2009-09-13 11:44:24 물론 때에 따라서는 팔로워가 친구만큼 가까운 관계인 경우도 있지만, 아주 실리적으로 관계를 맺는 약한 관계라고 할 수 있다. 미투데이 친구는 상호간에 관계를 맺지만, 트위터는 한쪽에서 일방적으로 팔로우하면 된다.(2tw 미투데이 트위터 차이점)2009-09-13 11:46:40 그래서 그런지 트위터 내에서는 하루에도 수많은 사람들이 팔로우를 했다가 얼마있다가 언팔로우를 했다가 하는 일이 비일비재하다. 그렇게 별 이유없이 팔로우는 하는 사람들은 대부분 자기를 팔로우하기를 바라는 마음에서 팔로우를 한다.(2tw 미투데이 트위터 차이점)2009-09-13 11:48:0[...]



블로그 글들 옮깁니다.

Sun, 06 Sep 2009 02:00:01 -0700

안녕하세요. 제 블로그를 아껴주시는 독자여러분.

아주 오랫동안 블로그를 버려 두다 시피하여 이젠 많은 분들이 관심을 잊어 버렸을 것 같기도 합니다만, 그럼에도 불구하고 여전히 구독해지 않고 기다려 주신분들께 우선 감사의 말씀드립니다.

제 글의 성격상 블로그라는 미디어의 형식에 어울리지 않는 것 같아 앞으로는 개발 관련 글들은 블로그에 작성하지 않고 위키 서비스에 올릴 생각입니다. 위키 서비스를 검색하던 차에 wikidot.com 이라는 괜찮은 서비스를 찾아서 여기 있는 글들을 차츰 차츰 옮길 생각입니다. 물론 여기에도 그대로 놔두긴 하겠지만 글들을 검토하면서 좀 더 다듬고 하는 것은 위키에서만 하게 될 것 같습니다.

아직은 이제 막 싸이트를 개설하고 위키 문법 공부하고 있는 중이라 글을 본격적으로 옮기진 못했구요. 앞으로 짬 날때마다 옮길 생각입니다.

위키 싸이트는 전 세계의 좀 더 많은 분들 소통하기 위해 한글과 영문 두 언어로 작성할 생각입니다.

위키 사이트 주소는  http://opensw.wikidot.com 입니다. 많은 관심 부탁드립니다.

어느 정도 글들을 옮긴 이후에 다시 공지드리도록 하겠습니다.
(image) (image) (image)
src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/365&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true">



C++ 이야기 서른번째: boost::shared_ptr performance

Sat, 27 Jun 2009 21:44:49 -0700

최근 제가 진행하던 프로젝트에서 boost::shared_ptr를 상당히 많이 사용해 왔었는데, 성능이 좋게 나오질 않아서 혹시나 해서 오늘 성능을 간단하게 측정해 봤더니 속도 차이가 상당히 많이 나는군요. 성능이 좀 느리겠거니 했는데 상상 이상이었습니다.(실은 이 문제 때문에 한바탕 홍역을 치뤘죠. ㅠ.ㅠ) 다음은 테스트 프로그램입니다. $ cat shared.cpp #include #include using namespace std; using namespace boost; class AClass { public:     void Op() const     {         ++i;     }     int Get() const     {         return i;     } private:     mutable int i; }; #ifdef SHARED_PTR void Foo(const shared_ptr& p) {     p->Op(); } #elif defined(SHARED_PTR_COPY) void Foo(shared_ptr p) {     p->Op(); } #else void Foo(AClass* p) {     p->Op(); } #endif int main(int argc, char* argv[]) { #if defined(SHARED_PTR) || defined(SHARED_PTR_COPY)     shared_ptr p(new AClass()); #else     AClass* p = new AClass(); #endif     int maxCnt = 1000000000;     if (argc >= 2)         maxCnt = atoi(argv[1]);     for (int i = 0; i < maxCnt; ++i)     {         Foo(p);     }     cout << p->Get() << endl;     return 0; } 이 테스트 프로그램은 세 가지 경우를 테스트하기 위한 것입니다. 1. raw pointer를 사용하는 경우: SHARED_PTR  또는 SHARED_PTR_COPY 가 정의되지 않은 경우입니다. 2. shared_ptr을 사용하는 경우: SHARED_PTR 이 정의된 경우입니다. Foo()를 호출할 때, const shared_ptr reference를 넘기기 때문에 복사가 일어나질 않습니다. 3. shared_ptr을 쓰면서 복사를 하는 경우: SHARED_PTR_COPY가 정의된 경우입니다. Foo()를 호출할 때, shared_ptr 객체를 넘기기 때문에 복사가 한 번 발생하고 이때, shared_ptr의 복사 생성자가 수행되면서 내부적으로 reference count를 증가시키고, 다시 함수에서 리턴될 때, reference count를 감소시키게 됩니다. 그리고 reference count 증가 및 감소는 보통 atomic operation으로 수행되기 때문에 보통의 증가/감소보다는 속도가 느린 걸로 알고 있습니다. 이 세가지에 대해 컴파일러 최적화 옵션 및 BOOST 옵션을 약간 달리 하면서 실행을 해 보았습니다. 다음은 테스트를 위한 Makefile 입니다. $ cat Makefile all: shared1 shared2 shared3 shared_copy1 shared_copy2 shared_copy3 plain1 plain2 plain3 #CFLAGS=-pg -g #LDFLAGS=-pg -g # CASE #1 CFLAGS1= # CASE #2 CFLAGS2=-O3 # CASE #3 CFLAGS3=-O3 -DBOOST_SP_DISABLE_THREADS LDFLAGS= shared1: shared1.o     g++ $(LDFLAGS) -o shared1 shared1.o shared_copy1: shared_copy1.o     g++ $(LDFLAGS) -o shared_copy1 shared_copy1.o plain1: plain1.o     g++ $(LDFLAGS) -o plain1 plain1.o shared1.o: shared.cpp     g++ $(CFLAGS1) -c -o shared1.o -DSHARED_PTR shared.cpp shared_copy1.o: shared.cpp     g++ $(CFLAGS1) -c -o shared_copy1.o -DSHARED_PTR_COPY shared.cpp plain1.o: shared.cpp     g++ $(CFLAGS1) -c -o plain1.o -DPLAIN shared.cpp shared2: shared2.o     g++ $(LDFLAGS) -o shared2 shared2.o shared_copy2: shared_cop[...]



김윤수의 인터넷 오늘은 - 2009년 1월 22일

Thu, 22 Jan 2009 11:33:07 -0800

이 글은 김윤수님의 2009년 1월 22일의 미투데이 내용입니다.

src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/363&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true">



김윤수의 인터넷 오늘은 - 2009년 1월 4일

Mon, 05 Jan 2009 11:34:55 -0800

이 글은 김윤수님의 2009년 1월 4일의 미투데이 내용입니다.

src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/362&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true">



김윤수의 인터넷 오늘은 - 2008년 12월 24일

Wed, 24 Dec 2008 11:32:32 -0800

  • Merry Christmas & Happy New Year! 전 11일 장기 휴가 돌입합니다. 저 없는 동안 잘 지내세요~ 인터넷 접속 안하기 한 번 실천해 봐야겠습니다.(인터넷생활)2008-12-24 18:09:36

이 글은 김윤수님의 2008년 12월 24일의 미투데이 내용입니다.

src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/361&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true">



C++이야기 스물아홉번째: Portable C++ Timer Class #2

Mon, 22 Dec 2008 05:35:29 -0800

If you are an English speaker, then follow this link. C++ Tips 29th: Portable C++ Timer Class #2 이번에는 timer 관련 클래스들에 어떤 멤버 함수와 멤버 변수를 정의해야할지에 대해 자세히 알아보겠습니다. 사용자가 가장 많이 사용하게될 클래스는 TimerDriver일테니 이것부터 시작해 보도록 하겠습니다. 저번글에서 말씀드렸던 것처럼 TimerDriver는 등록된 타이머들이 정확한 시간에 expire되도록 해주는 클래스입니다. 이점을 고려하면 타이머 인스턴스들을 등록하고 등록해제하는 멤버 함수는 누가 봐도 필요할 것 같습니다. class TimerDriver {public:    TimerId RegisterTimer(const Timer& t);    void UnregisterTimer(TimerId tid);}; 이 인터페이스를 정의하고 나면 등록된 타이머 인스턴스들을 저장해 놓을 저장 공간이 필요하다는 걸 금방 알게 됩니다. 그럼 어떤 데이터 구조가 저장 공간으로 적당할까요? 가장 적당한 데이터 구조를 택하려면 아무래도 사용자가 TimerDriver를 사용하는 패턴을 먼저 알아야 할 것 같습니다. 지금까지 정의한 멤버 함수는 RegisterTimer(), UnregisterTimer() 두 개가 있고, 이 둘은 결국 삽입과 삭제에 해당합니다. 그리고 타이머 인스턴스들 하나 하나를 건드리면서 드라이브 할 수 있습니다. 그렇지만 사용자가 정렬된 타이머 리스트를 필요로 하거나, 타이머 인스턴스를 직접 접근하거나, 타이머 인스턴스를 상당히 빠르게 검색해야할 필요성은 없을 것입니다. 그래서 저는 std::list가 등록된 타이머 인스턴스 저장 데이터 구조로 가장 적당하다고 생각합니다. #include class Timer;class TimerDriver {public:    TimerId RegisterTimer(const Timer& t);    void UnregisterTimer(TimerId tid);private:    std::list timer_list_;}; 다음으로 RegisterTimer() 와 UnregisterTimer()의 입력 인자와 리턴값에 대해 생각해 보겠습니다. 제가 RegisterTimer()의 리턴값과 UnregisterTimer()의 입력인자로 TimerId라는 타입을 도입했습니다. 'TimerId' 타입의 필요성은 분명해 보이는데... 어떤식으로 'TimerId' 타입을 정의해야할까요? TimerDriver가 내부적으로 식별자 풀(identifier pool)을 관리해야할까요 아니면 TimerId가 그냥 Timer*이면 될까요? 식별자 풀을 관리한다면 각 타이머 인스턴스에 할당된 식별자는 어디에 저장해야할까요? timer_list_는 list라고 선언해도 무방할까요 아니면 다른 뭔가로 선언해야할까요? 예를 들어, list와 같이 말이죠. 우리가 결론에 도달할 때까지는 이런 수 많은 질문들이 머리속을 맴돌게 됩니다. 혼란 그 자체죠? 이런 간단한 클래스를 설계하는데도 말입니다. 그렇지만, 소프트웨어 개발자로서 선택에 대한 분명한 이유를 찾아가며 이런 혼란스러움을 해결해 가야 합니다. 삶이란 게 문제로 가득차 있고, 산다는 것 자체가 해답을 찾아가는 과정 아닐까요? 그러니 너무 괴로워하지 마시고 맘을 가다듬어 보시죠. 사실 이 모든 문제들이 서로 연결되어 있습니다. 한 문제에 대한 해결책을 찾게 되면... 짠! 하고 다른 모든 문제들에 대한 해결책도 찾을 수 있게 될테니까요. 그럼 문제점을 하나씩 해결해 보시죠. 숨을 기~~~~~~~~~~~~~피 들이 쉬시고~~~ TimerId! TimerDrive[...]



김윤수의 인터넷 오늘은 - 2008년 12월 20일

Sat, 20 Dec 2008 12:18:08 -0800

이 글은 김윤수님의 2008년 12월 20일의 미투데이 내용입니다.

src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/359&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true">



김윤수의 인터넷 오늘은 - 2008년 12월 18일

Thu, 18 Dec 2008 11:32:33 -0800

  • 한 동안 블로그에 글 못 올릴 것 같습니다. 양해 바랍니다.(블로그 휴업)2008-12-18 22:33:52

이 글은 김윤수님의 2008년 12월 18일의 미투데이 내용입니다.

src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/358&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true">



김윤수의 인터넷 오늘은 - 2008년 12월 9일

Mon, 08 Dec 2008 11:32:30 -0800

이 글은 김윤수님의 2008년 12월 9일의 미투데이 내용입니다.

src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/357&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true">



C++이야기 스물아홉번째: Portable C++ Timer Class #1

Mon, 08 Dec 2008 05:37:17 -0800

If you are an English speaker, then follow this link. C++ Tips 29th: Portable C++ Timer Class #1 우리네 생활이 온통 시간에 둘러쌓여 있듯이, 응용프로그램부터 펌웨어에 이르는 프로그램도 시간에 둘러쌓여 있지요. 예를 들자면, 달력 프로그램은 시간과 연관되어 있는 약속과 할일들을 처리하고, 검색 로봇은 주기적으로 페이지를 긁어 오고, 멀티미디어 재생기는 제 시간에 맞춰서 데이터 저장소로부터 열심히 데이터를 끌어 오고, TCP/IP 위에서 동작하는 통신 미들웨어는 데이터 교환이나 요청한 연산에 대해 타임아웃을 처리하고, 디바이스 드라이버는 주기적으로 디바이스에 상태 체크 요청을 보냅니다. 이렇게 시간은 워낙 근본적인 개념이라 아주 작은 프로그램을 개발하는 경우를 제외한다면 대부분 타임아웃이나 주기적인 이벤트를 처리할 수 있는 라이브러리가 필요하게 됩니다. 그래서 이번과 앞으로 몇 번에 걸쳐 boost 라이브러리를 활용하여 타임아웃이나 주기적인 이벤트를 처리할 수 있는 타이머 클래스를 구현하는 방법에 대해 얘기하려고 합니다. 타이머와 연관된 기본적인 개념을 먼저 한 번 생각해 보죠. 타이밍 이벤트는 주기적으로 발생하거나 딱 한 번만 발생한다. 타이밍 이벤트가 발생하면 특정 작업을 처리해야 한다. 정확한 시간에 타이밍 이벤트가 발생하도록 해주는 일종의 구동기가 존재한다. 저는 이 정도 개념이 우선 떠오르네요. 그럼 먼저 첫번째 개념에서 어떤 클래스를 정의해야 하는지부터 시작해 볼까요? 다음과 같이 enum 값들로 두 가지 타입을 다 지원하는 클래스 하나를 정의할 수도 있을 겁니다. class Timer { public:   typedef enum {     PERIODIC_TIMER,     ONE_SHOT_TIMER   } Type; private:   Type m_type; }; 서로 다른 두 개념을 클래스 하나로 묶어 놓은 설계가 과연 좋은 설계일까요? 좀 더 주의깊게 생각해 보시죠. 이 설계대로 하면 생성자는 어떻게 작성해야 할까요? #include // for time_duration class Timer { public:   typedef enum {     PERIODIC_TIMER,     ONE_SHOT_TIMER   } Type;   Timer(Type type, const boost::posix_time::time_duration& td); private:   Type m_type; }; 'type' 인자의 의미는 분명하지만, 'td' 인자는 어떤 것을 뜻할까요? 보통 주기적인 이벤트는 주기(== 'td')라는 게 필요하고, 타임아웃 이벤트는 그 이벤트가 발생할 시간(== 현재 시간 + 'td')을 필요로 할테니... 'td' 인자가 뜻하는 바는 'type'에 따라 달라지겠죠? 그렇다면,  Timer::Timer() 을 구현한 코드가 아무래도 다음 코드에서 보시는 것처럼 'type' 값에 의존적인 코드가 될 것 같군요. Timer::Timer(Type type, const boost::posix_time::time_duration& td) {   switch (type)   {   case PERIODIC_TIMER:     ......     break;   case ONE_SHOT_TIMER:     ......     break;   default:     break;   } } 이렇게 되면 새로운 타입의 타이머를 추가할 때마다 이 생성자를 수정해야할 필요가 있다는 건 쉽게 눈치 채실 수 있으시겠죠? 상당히 심각한 유지보[...]



김윤수의 인터넷 오늘은 - 2008년 12월 7일

Sun, 07 Dec 2008 11:32:09 -0800

이 글은 김윤수님의 2008년 12월 7일의 미투데이 내용입니다.

src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/355&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true">



김윤수의 인터넷 오늘은 - 2008년 12월 3일

Tue, 02 Dec 2008 11:32:31 -0800

이 글은 김윤수님의 2008년 12월 2일에서 2008년 12월 3일까지의 미투데이 내용입니다.

src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/354&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true">



티스토리 달력 공모전 응모

Tue, 02 Dec 2008 08:36:57 -0800

음... 올해 있었던 추억을 담아 응모해 봅니다.

(image)

여름에 아이들과 함께 동네 야외 수영장 갔을 때 찍었던 사진입니다. 오빠와 동생이 함께 노는 모습이 보기 좋아서 선정해 봤습니다. 7월 사진으로 적당할 것 같네요.

(image)

위 사진은 대관령 양떼 목장에 갔을 때 찍은 하늘 사진입니다. 날씨가 아주 맑은 날이어서 하늘이 너무 멋있어 보이더군요. 9월 사진으로 적당할 것 같네요.

그리고 하늘의 구름과 땅의 양떼가 어우러진 이 사진도 좋은 것 같습니다. 마찬가지로 9월이 적당할 것 같네요.

(image)

src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/353&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true">



김윤수의 인터넷 오늘은 - 2008년 11월 30일

Sun, 30 Nov 2008 11:32:18 -0800

이 글은 김윤수님의 2008년 11월 30일의 미투데이 내용입니다.

src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/352&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true">



김윤수의 인터넷 오늘은 - 2008년 11월 28일

Thu, 27 Nov 2008 11:32:27 -0800

스마트폰이 노트북 밀어낸다: 스마트폰 세상이 오고 있군요. 무선 인터넷 세상도 같이 와야 할텐데 말이죠. (인터넷오늘은 북마크 스마트폰) 2008-11-27 23:15:03 맥용 와이브로 USB 모뎀이 있었군요 (인터넷오늘은 북마크 와이브로 맥) 2008-11-27 23:28:43 다음, 부동산정보도 네이버 제쳤다: 다음이 만년 2등에서 벗어날 수 있을까요? 지금은 너무 많이 차이가 나서… 다음이 좀 더 잘해준다면 선의의 경쟁이 될 수 있을텐데요 (인터넷오늘은 북마크 다음 전 네이버와 다음의 주주예요 ^^) 2008-11-27 23:38:11 상장사 3분기 누적수출 224조, 25.5%↑: 환율의 영향이 크긴 컷었나 보군요. 예상되는 바였습니다. 좀 더 지나면 환율 영향은 사라지고 글로벌 경기 침체 영향으로 수출이 줄어들지 않을까 걱정되네요. (인터넷오늘은 북마크 수출 경제) 2008-11-27 23:43:17 [내일의전략]산타랠리 기대해도 좋다: 단기 랠리에 그칠 것 같은데, 언론사들 항상 김치국부터 마신다 (인터넷오늘은 북마크 경제 주식시장) 2008-11-27 23:51:20 삼성서버엔 삼성SSD가 없다: 이 기사는 삼성전자 내부 사정을 모르는 기자가 작성한 듯. 작년에도 삼성전자 반도체 사업부가 자사 휴대폰 사업부보다 애플에 더 싼 값에 플래스 메모리를 공급했다는 걸 아시는지 모르시는지… (인터넷오늘은 뉴스 삼성전자) 2008-11-28 00:00:18 '마이너리티 리포트' 컴퓨터 기술, 현실화된다: 이거 제품으로 나오면 꼭 사고 싶네요. 2~3년내 상품화 목표래요. (인터넷오늘은 북마크 뉴스 HCI) 2008-11-28 00:08:49 한국판 '구글맵스' 흥행 성공할까?: 이런 소식을 이제서야 접하다니… 쩝~ 옛날에 구글이 한국 관련 데이터가 너무 부족하다고 1년전에 글을 썼었는데… 이제서야 데이터를 확보한건지 아니면 규제문제 때문이었는지… 아무튼 환영~ (인터넷오늘은 북마크 뉴스 구글맵스 한국) 2008-11-28 00:17:07 DB도 토종 오픈소스 가능한가?…큐브리드의 대담한 도전: 다른 건 몰라도 License는 정말 잘 정했다. GPL과 BSD의 절묘한 조합이라고 해야겠네. 기술과 법을 다 잘 이해해야만 정할 수 있는 정책이다. (인터넷오늘은 북마크 뉴스 오픈소스) 2008-11-28 00:31:33 이 글은 김윤수님의 2008년 11월 27일에서 2008년 11월 28일까지의 미투데이 내용입니다. src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/351&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true"> [...]



김윤수의 인터넷 오늘은 - 2008년 11월 27일

Wed, 26 Nov 2008 11:33:04 -0800

이 글은 김윤수님의 2008년 11월 27일의 미투데이 내용입니다.

src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/350&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true">



다음 모바일 서비스 블로거 간담회에 다녀오다

Tue, 25 Nov 2008 14:00:00 -0800

11월 26일 저녁 7시 다음 양재 사옥 3층에서 개최된 "다음 모바일 서비스 블로거 간담회"에 다녀왔습니다. 저로서는 아주 오랜만의 서울 나들이였습니다. 워낙 회사일도 바쁘고, 집안 가장으로서 해야할 일도 많고 해도 시간 내기가 여간 어렵지 않더군요. 그런 만큼 이번에는 머리도 식힐 겸 요즘 모바일 인터넷이 어떻게 돌아가는지도 알아볼 겸 해서 기대하는 마음으로 참석했습니다. 행사장에 늦게 도착하지 않기 위해 급하게 나섰던지 너무 일찍 도착해서 주변에서 살짝 방황 좀 하다가 6:30분 쯤에 행사장에 들어갔습니다. 지동아빠님(첨엔 몰랐는데 나중에 알았다는...)께서 식사는 6:50분에 제공되고, 행사는 식사후에 시작하게 된다고 하시더군요. 그래서 잠시 기다리는 동안 인터넷에 접속하려고 했으나... 헉! 무선랜이 안되더군요. ㅠ.ㅠ 순간 당황해서 패닉 상태에 빠질 뻔 했습니다. 혼미해지던 정신을 부여잡고 뭘해야하나 고민하던 중 고이고이님께서 아는체를 하셔서 겨우 정신 수습했습니다. 이 자리를 빌어서 고이고이님께 감사 ^^ 식사할 때는 같은 테이블에 빨판님, 함장님, 고이고이님, 미소챨스님과 합석했습니다. 행사 첫 오프닝은 oojoo라는 id로도 유명하신 김지현님(회사내 직책은 본부장이신가 보더군요)께서 하셨고, 기업이 블로그를 운영하는 것은 공개할 수 있는 정보와 공개해서는 안되는 정보 사이를 잘 조절해야 해서 어려움이 많지만 서비스를 혼자 만드는 거이 아니라 사용자와 같이 만든다고 생각하기 때문에 외부와 소통하기 위해 블로그를 운영하고 있고, 이번 간담회도 같은 맥락에서 1차로 준비한 서비스에 대한 의견을 듣고 싶어서 개최한 것이라고 배경 설명을 해 주셨습니다. 그리고 이어서 지도 위에서 무궁 무진한 서비스가 펼쳐질 수 있다고 생각하고, 모바일 서비스의 킬러앱을 맵으로 보고 있다고 설명하시면서, 다음이 맵에 어떤 투자를 하고 있는지 실제 시연 장면을 통해 보여주셨습니다. 이 대목에서 기밀사항이라 사진 촬영은 금지! 저야 카메라가 없으니 말하지 않아도 찍을 수 없는 상황이었죠 ^^ 언뜻 보기에 맵 해상도가 상당히 고화질로 보이더군요. 스트릿뷰, 스카이뷰도 지원되고 요즘은 대부분 포털들이 고화질 맵 서비스를 제공하고 있어서 크게 달라 보이진 않았습니다. (여기서 아마 다음의 고민이 시작되겠지요? 어떻게 타사와 차별화 시킬 것인가?) 이런 맵을 별도의 어플리케이션을 통해 모바일 폰에 올리려나 보더군요. 이런 맵 위에서 지명 검색, UCC 검색, 드라마 촬영지 검색, 경로 검색(버스, 지하철, 버스&지하철, 최적 경로, 최단 경로) 등도 가능하다고 합니다. 나중에 지동아빠님(모바일 애플리케이션 담당이시랍니다)께서 직접 테이블에 오셔서 시연도 해주셨습니다. 내년 쯤에서(내년 초라고 했는지 말이라고 했는지 기억이 나질 않네요 ㅠ.ㅠ) 모바일 맵 서비스[...]



C++이야기 스물여덟번째: map container에 STL algorithm적용하기

Sun, 23 Nov 2008 14:00:00 -0800

If you are more familiar with English, then follow this link. C++ Tips 28th: Applying STL Algorithms to a Map Container 여러분은 map container에 STL algorithm을 적용해 보신 적 있으신가요? map은 key=value pair를 저장해 두는 container라서 다른 container에 비해 STL algorithm을 적용하기가 쉽지 않더군요. map은 key 보다는 value에 관심이 있는 container라서 STL algorithm을 수행할 때도 key-value pair에 대해서 특정 작업을 수행하기 보다는 value에 대해서 어떤 작업을 수행하기를 원하는 경우가 많은데, STL algorithm 및 표준 함수 객체들이 map에 맞춰져 작성되어 있질 않아서 이걸 하기가 쉽지 않더군요. 그래서 별도의 Adaptor class를 정의하는 경우가 많습니다. 한 번 예를 들어 보겠습니다. 다음과 같은 클래스가 정의되어 있다고 가정해 보시죠. class Elem { public:     Elem() : m_name(), m_val() {}         Elem(const string& name, int val) : m_name(name), m_val(val) {}         const string& GetName() const     {         return m_name;     }         int GetValue() const     {         return m_val;     }         void SetValue(int val)     {         m_val = val;     }         void Print() const     {         cout << GetName() << "'s value ==> " << GetValue() << endl;     }     private:     string m_name;     int m_val; }; 이 Elem 를 담는 map을 다음과 같이 정의해서 몇 개를 집어 넣어 보도록 하겠습니다. // 앞으로 설명에서 나오는 m container는 이걸 뜻합니다 map m;     m["1"] = Elem("1", 1); m["2"] = Elem("2", 2); m["3"] = Elem("3", 3); m["4"] = Elem("4", 4); m["5"] = Elem("5", 5); 이 map에 담긴 모든 Elem 들의 값을 얻어내고 싶은 경우를 생각해 보겠습니다. 그렇다면 다음과 같이 for 루프를 작성할 수 있습니다. // 먼저 값을 담을 vector를 정의합니다 vector vi(m.size()); // 그리고 for 루프를 돌립니다 for (map::iterator it = m.begin(); it != m.end(); ++it) {   vi.push_back(it->second.GetValue()); } 소위 STL 좀 쓴다하는 여러분이 위와 같은 코드를 그냥 둘리 만무합니다. 어떻게 하면 저 for 루프를 STL 알고리즘으로 바꿀 수 없을까를 고민하시겠지요. 그리고 transform을 쓰면 되겠구나라고 맘을 먹습니다. // 먼저 algorithm header 파일을 포함해야죠 #include #include ...... vector vi(m.size()); // m 에 들어가 있는 것은 포인터가 아니라 값이 들어가 있으므로 mem_fun이 아닌 // mem_fun_ref를 사용하여 멤버 함수 객체를 만듭니다 transform(m.begin(), m.end(), vi.begin(), mem_fun_ref(&Elem::GetValue)); [...]



김윤수의 인터넷 오늘은 - 2008년 11월 21일

Fri, 21 Nov 2008 11:33:01 -0800

  • F# Primer: F# 소개 기사네요. 이제는 함수형 언어에도 관심을 많이 가져 봐야 겠어요 (SW개발 프로그래밍언어 fsharp F#) 2008-11-21 22:57:30

이 글은 김윤수님의 2008년 11월 21일의 미투데이 내용입니다.

src="//www.facebook.com/plugins/like.php?href=http://yesarang.tistory.com/347&layout=standard&show_faces=true&width=310&action=like&font=tahoma&colorscheme=light&height=65" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:310px; height:65px;" allowTransparency="true">