앞 선 글 중 ‘std::thread - 2. Join’에서 join을 호출하지 않은 경우 에러 창이 발생하였습니다.


 

이것은 C++11 thread 사양에 의해서 thread 오브젝트가 파괴될 때 join이나 detach를 호출하지 않은 경우 std::terminate를 호출하여 프로그램을 종료하도록 되어 있기 때문입니다.

 

< 예제. 9 >

#include <thread>

#include <iostream>

 

int main()

{

           int nThreadRunCount = 0;

          

           {

                      std::thread Thread = std::thread( [&] ()

                       {

                          for( int i = 0; i < 10; ++i )

                          {

                                ++nThreadRunCount;

                                                               

                                std::cout << "Thread1 ID : " << Thread.get_id() << std::endl;

                          }

                       } );

           }

 

           getchar();

           return 0;

}

 


<예제.9>를 실행하면 에러가 발생하고 아래의 콜스택을 보면



thread 오브젝트의 소멸자에서 terminate를 호출하는 것을 알 수 있습니다.



이것으로 thread에 대해서 기능 위주로 간단하게 살펴 보았습니다. 앞으로 공부해야 할 것들이 더 있어서 남은 것들을 설명 후 다시 thread 사용에 대해서 깊게 들어 가겠습니다.

 

다음부터는 병렬 프로그래밍에서 절대 빠질 수 없는 동기화 객체에 대해서 설명하겠습니다.

 

 

by 흥배 2013. 5. 28. 08:00





by 흥배 2013. 4. 23. 21:22

예전에 적은 글을 출판사에서 편집을 해서 이번에 무료 이북으로 나왔습니다.

STL 초보자 용 책이라고 보시면 됩니다. 
필요하신 분들은 다운로드 하세요^^

http://www.hanb.co.kr/ebook/look.html?isbn=9788979149937#binfo2



by 흥배 2012. 12. 22. 14:21
  • blueasa 2012.12.26 11:49 신고 ADDR EDIT/DEL REPLY

    감사합니다. (_ _)

  • Mr.K 2012.12.26 17:34 ADDR EDIT/DEL REPLY

    감사합니다. 덕분에 좋은것 많이 배워갑니다.^_^

  • 성일 2013.01.03 11:21 ADDR EDIT/DEL REPLY

    감사합니다.

  • msahn 2013.01.11 17:05 ADDR EDIT/DEL REPLY

    좋은 정보, 좋은 책. 감사합니다.

int, short, float 타입 등의 수치 타입의 최대 값과 최소 값을 알고 싶을 때는 

STL에 있는 nurmeric_limit를 사용합니다.


너무 간단한 내용이니 아래의 예제 코드로 설명을 끝내겠습니다^^


#include <iostream>

#include <limits>


int main()

{

std::cout << "float 타입의 최대 값:  " << std::numeric_limits<float>::max( ) << std::endl;

std::cout << "double 타입의 최대 값:  " << std::numeric_limits<double>::max( ) << std::endl;

std::cout << "short 타입의 최대 값:  " << std::numeric_limits<short>::max( ) << std::endl;

std::cout << "int 타입의 최대 값:  " << std::numeric_limits<int>::max( ) << std::endl;

std::cout << "short 타입의 최대 값:  " << std::numeric_limits<short>::max( ) << std::endl;

std::cout << "__int64 타입의 최대 값:  " << std::numeric_limits<__int64>::max( ) << std::endl;



std::cout << "float 타입의 최소 값:  " << std::numeric_limits<float>::min( ) << std::endl;

std::cout << "double 타입의 최소 값:  " << std::numeric_limits<double>::min( ) << std::endl;

std::cout << "short 타입의 최소 값:  " << std::numeric_limits<short>::min( ) << std::endl;

std::cout << "int 타입의 최소 값:  " << std::numeric_limits<int>::min( ) << std::endl;

std::cout << "short 타입의 최소 값:  " << std::numeric_limits<short>::min( ) << std::endl;

std::cout << "__int64 타입의 최소 값:  " << std::numeric_limits<__int64>::min( ) << std::endl;


return 0;

}


< 결과 >







by 흥배 2012. 11. 1. 09:00

이번에 설명할 is_partitioned, partition_point는 그 이름처럼 앞서 소개한 partition_copy와 관계가 있는 알고리즘 입니다.

 

is_partitioned의 원형

template<class InputIterator, class BinaryPredicate>

    bool is_partitioned(

        InputIterator _First,

        InputIterator _Last,

        BinaryPredicate _Comp

    );

 

partition_point의 원형

template<class ForwardIterator, class Predicate>

    ForwardIterator partition_point(

        ForwardIterator _First,

        ForwardIterator _Last,

        Predicate _Comp

    );

 

is_partitioned는 데이터셋의 요소가 전반 부와 후반 부 두 개로 나누어져 있는지 조사할 때 사용하고, partition_point는 두 개로 나누어져 있는 데이터셋에서 후반 부의 첫 번째 요소를 가리키는 반복자를 반환합니다.

 

약간 설명이 애매하죠?^^; 

예를 들어 설명하면 온라인 FPS 게임에서 8명이 각각 4명씩 레드 팀과 블루 팀으로 나누어서 게임을 하는 경우 vector로 된 StagePlayers(온라인 게임에서 방에 들어온 유저들을 저장)에 앞 부분에는 레드 팀 플레이어 4명을 차례로 저장하고그 이후에 블루 팀 플레이어를 저장하고 있는지 조사하고 싶을 때 is_partitioned알고리즘을 사용하면 알 수 있습니다(맞다면 true를 반환합니다). 그리고 StagePlayers에서 블루 팀의 첫 번째 플레이어에 접근하고 싶다면 partition_point를 사용합니다.  


나름 쉽게 설명한다고 했는데 이해 가시나요만약 이해가 안 간다면 예제 코드를 봐 주세요^^

 

예제 >

#include <iostream>

#include <algorithm>

#include <vector>

#include <list>

using namespace std;

 

struct PLAYER

{

           int CharCD;

           bool IsRedTeam;

};

 

 

int main()

{

           vector< PLAYER > StagePlayers1;

           PLAYER player1; player1.CharCD = 1;         player1.IsRedTeam = true;          StagePlayers1.push_back( player1 );

           PLAYER player2; player2.CharCD = 2;         player2.IsRedTeam = true;          StagePlayers1.push_back( player2 );

           PLAYER player3; player3.CharCD = 3;         player3.IsRedTeam = true;          StagePlayers1.push_back( player3 );

           PLAYER player4; player4.CharCD = 4;         player4.IsRedTeam = false;                     StagePlayers1.push_back( player4 );

           PLAYER player5; player5.CharCD = 5;         player5.IsRedTeam = false;                     StagePlayers1.push_back( player5 );

           PLAYER player6; player6.CharCD = 6;         player6.IsRedTeam = false;                     StagePlayers1.push_back( player6 );

           PLAYER player7; player7.CharCD = 7;         player7.IsRedTeam = false;                     StagePlayers1.push_back( player7 );

 

           bool IsPartitioned = is_partitioned( StagePlayers1.begin(), StagePlayers1.end(),

                                                                                     []( PLAYER player ) -> bool { return player.IsRedTeam; } );

           if( IsPartitioned ) {

                     cout << "레드 팀과 블루 팀으로 구분 되어 나누어져 있습니다." << endl;

           } else {

                     cout << "레드 팀과 블루 팀으로 구분 되어 있지 않습니다." << endl;

           }

 

           vector< PLAYER >::iterator IterFirstBlueTeamPlayer = partition_point( StagePlayers1.begin(),StagePlayers1.end(),

                                                     []( PLAYER player ) -> bool { return player.IsRedTeam; } );

           if( IterFirstBlueTeamPlayer != StagePlayers1.end() ) {

                     cout << "첫 번째 블루 팀 플레이어캐릭터 코드 : " << (*IterFirstBlueTeamPlayer).CharCD << endl;

           }

 

                    

           vector< PLAYER > StagePlayers2;

           StagePlayers2.push_back( player7 );

           StagePlayers2.push_back( player6 );

           StagePlayers2.push_back( player1 );

           StagePlayers2.push_back( player5 );

           StagePlayers2.push_back( player4 );

           StagePlayers2.push_back( player3 );

           StagePlayers2.push_back( player2 );

          

           IsPartitioned = is_partitioned( StagePlayers2.begin(), StagePlayers2.end(),

                                                                                     []( PLAYER player ) -> bool { return player.IsRedTeam; } );

           if( IsPartitioned ) {

                     cout << "레드 팀과 블루 팀으로 구분 되어 나누어져 있습니다." << endl;

           } else {

                     cout << "레드 팀과 블루 팀으로 구분 되어 있지 않습니다." << endl;

           }

 

           getchar();

           return 0;

}

 

결과 >

 

예제 코드를 보니 쉽게 이해 되시죠그럼 저는 아는 걸로 생각하고 다음 포스팀에서는 다른 알고리즘을 설명하겠습니다^^

by 흥배 2012. 9. 5. 19:26

VC11 STL 컨테이너들은 이전 버전에 비해서 크기가 작아져서 메모리를 절약할 수 있게 되었습니다. 이전 버전과 다르게 VC11부터는 데스크탑 뿐만이 아닌 테블렛이나 스마트폰의 모바일 플랫폼 개발에서도 사용되므로 메모리 절약은 적지 않은 도움이 되리라 생각합니다.

 

아래 표는 x86(32비트 또는 ARM) x64(64비트) 플랫폼에서 각 VC 버전 별로 얼마만큼의 메모리를 사용하는 잘 표시하고 있습니다.

 

이 표는 VC11 뿐만이 아닌 이전 버전 사용자들에게도 도움이 될 것 같습니다. 저와 같은 서버 프로그래머들은 서버 프로그램이 설정한 동접자 수에서 어느 정도의 메모리를 소비할지 어느 정도 계산하고 있어야 하는데 이 표를 보면 메모리 계산할 때 도움이 될 것입니다

 

표의 바이트 사이즈는 Release 버전 기준입니다. 표에서 'VC9 SP1 SCL=0'SCL _SECURE_SCL를 뜻하는 것으로 원래 SCL은 기본은 1인데, 최고 스피드를 위해서 수동으로 SCL0으로 설정한 것입니다. VC10 VC11에서는 기본으로 _SECURE_SCL 0으로 되어 있습니다.

 


표의 출처는 MSDN입니다^^




by 흥배 2012. 7. 12. 09:00

예전에  http://jacking.tistory.com/154 이 글을 통해서 간단하게 VC++의 연관 컨테이너의 성능을 테스트해 본적이 있습니다.

그 때는 VC++ 9 환경에서 테스트를 했는데 이번에는 VC++ 11(RC)에서 테스트 해 보았습니다.

그때 사용했던 코드를 거의 그대로 사용했습니다(그래서 손 볼 것이 좀 있습니다^^;)


성능은 역시나(?) CAtlmap이 제일 빠릅니다. 또 unordered_map이 이전에 비해서 많이 빨라졌네요

일전에 VC++ 팀 블로그에서 성능이 개선되었다고 하던데 맞네요


코드를 올리니 혹시 관심 있는 분들은 좀 더 다양하게 테스트 해보시고 공유 부탁합니다^^





ContainerPerformance.zip


by 흥배 2012. 7. 5. 09:00
C++, STL

일본의 콘솔 게임 개발자의 글을 웹서핑 중 보고 옮겨봅니다.

 

운 좋게 STL에 대해서 거부감 없는 곳에서 일하고 있지만 어떤 곳에서는 STL은 게임 개발에는 적합하지 않다고 사용을 금지하는 곳이 있음(역주 :제 기억으로 한국도 2002~5년 정도까지는 커뮤니티에서 STL로 불꽃(?) 토론이 있었죠. 아마 GPGStudy에 가면 아직 글이 있을 듯하네요).

 

STL은 그 특성을 잘 모르면 골치 아플 수 있음. 특히 콘솔 게임기는 메인 메모리가 PC에 비해서 엄청나게 작은데 그 작은 메모리로 실행 바이너리나 힙 영역으로 사용해야 한다. 메모리 관리에 대해서 엄격하므로 template는 사용 방법에 따라서 바이너리 사이즈가 켜져서 사용을 어느 정도 제한할 수 밖에 없음(역주 : 저 개인적으로 이 메모리 관리 때문에 PC 개발만 해 본 사람은 콘솔 게임 개발이 무척 어려울 것이라고 생각합니다).

 

std::list, std::map 등은 사용하면 사용할수록 내부에서 메모리 단현화 시키므로 힙 영역의 총 량은 남아있지만 사용 가능한 용량이 부족하게 되는 경우가 있다. 그래서 본인이 있는 곳에서는 모든 게임 코드에 std::list, std::map 등의 메모리 단편화를 만드는 컨테이너는 사용을 피하도록 하고 있으며 만약 신입이 깜박하고 사용한 경우에는 왜 게임에서 사용하면 안 되는지 알려주고 구조를 바꾸도록 한다.

 

그런데 어떤 게임 개발 회사의 개발자가 만든 책에는 std::vector를 혹평하고 std::map을 절찬한 경우가 있다.

 

STL을 금지 시키는 사람의 가장 큰 이유는 자신이 STL이 무엇인지 잘 모른다는 것. 보통 STL 이라고 하면 컨테이너만 생각하는데 컨테이너 + 이터레이터 + 알고리즘 + functor 이다. 알고리즘은 STL 컨터이너 뿐만이 아닌 배열도 사용할 수 있다.

 

출처 : http://d.hatena.ne.jp/masfj/20120308/1331220846

 

 

 

ps : 제 경험으로도 애자일, TDD, STL, boost 라이브러리 등을 반대하는 사람들은 대부분 아는 사람이 아니고 잘 모르는 사람이 반대하더군요(왠지 적어보니 당연한 것 같기도 ㅎㅎ). 그래서 반대 논리가 너무 빈약하고 억지에 가까운 자신의 생각만을 이야기 하더군요(당연하지만 본인은 절대 객관적이라고 이야기하죠).

by 흥배 2012. 4. 12. 09:00
  • 쟁이 2012.04.12 11:35 ADDR EDIT/DEL REPLY

    이 글의 내용이 이해가 되지 않습니다. 제가 STL에 대해서 잘 몰라서 그런가하고 넘어가려니 뭔가 찜찜하고...

    원문의 취지는,
    1. STL의 사용으로 메모리 효율이 악화되기 때문에 메모리가 제한적인 콘솔에서는 사용이 기피된다.
    2. 1과 같이 주장하는 사람은 STL에 대해서 잘 모르고 하는 소리다.

    2와 같이 1의 주장을 반박을 하기 위해서는 1의 기피 이유인 메모리의 사용이 비효율적이지 않음을 지적해야 하는 것 아닌가요?
    그런데, 2와 같이 반박하는 이유가 STL은 컨테이너뿐 아니라 이터레이터+알고리즘+Functor라는... STL의 일반적인 속성을 들어서 반박하고 있네요.

    제가 보기엔 오히려 2의 반박이유가 문제의 초점을 흐리고 있는 걸로 보이는데.....
    혹시 제가 잘못 이해하고 있는 건가요?

    • 흥배 2012.04.12 14:23 신고 EDIT/DEL

      글의 내용은
      STL은 좋은 것이다. 그러나 잘 모르고 사용하면 오히려 해를 입을 수 있다.
      그런데 STL을 반대하는 사람들은 잘모르는 사람들이 좋고 나쁨을 따지지 않고 반대한다.
      STL을 조심해야 하는 점으로 메모리 단편화가 있다(물론 해결책은 있습니다)
      라는 것입니다.

  • 나그네 2012.04.13 09:16 ADDR EDIT/DEL REPLY

    STL, boost의 경우 많이 쓰려고 노력하는 편입니다.
    물론 확실히 알고 쓰고 있습니다.(알고 쓰는 부분만 있다는것이죠)
    허나 TDD, 애자일은 약간 반대입장입니다.
    위의 것 둘다 해보았고 프로젝트에 적용해보았습니다만..
    이건 아래 두개는 정말 프로젝트에 녹이기기 힘들더군요. 프로그래머의 의식과 개인들의 사고방식에 관여가 많이 되어 있기 때문입니다.
    정말 능통한사람이 3사람정도는 있어야 가능할것같더군요..
    우리 같이 공부하면서 해보자...이건 경험상 비추입니다.

    • 흥배 2012.04.13 12:22 신고 EDIT/DEL

      네 저도 TDD나 애자일을 경험해봐서 이게 완전무결한 것이 아니라서 단점도 있고 쉽게 할 수 없다는 것을 알고 있습니다. 다만 저는 반대를 하더라도 나그네님처럼 직접 해보고(아님 최소한 공부해보고) 장단점을 파악한 후 현재 상황에서는 득이 없다면 도입하지 말고, 다른 사람들에게도 이유를 잘 설명해주고 반대를 했으면 좋겠습니다^^

      TDD나 애자일은 프로젝트의 시간적 여유, 윗분이나 프로그래머들의 강력한 의지가 없으면 정말 하기 힘들다고 생각합니다. 효과도 한동안은 직접적으로 들어나지도 않고, 이야기하신 것처럼 잘 아는 사람이 없으면 너무 헤멜수 있어서 초기에는 장점보다 단점이 더 부각될 수 있다고 생각합니다

  • 엑스터 2012.04.24 12:18 ADDR EDIT/DEL REPLY

    STL, Boost 의 경우 새로 만드는 것보다 이해하고 잘 사용하게 되는 것이 더 유용하고 빠를 것 같은데, 새로 만드는 것을 선호하는 경우가 많네요.

    STL 의 인터페이스가 마음에 안 든다고 바꾸는 경우도 봤는데, C++ 을 C++ 로 생각하지 않고 다른 언어로 바꾸려는 듯한 느낌을 받았습니다.

    • 흥배 2012.04.24 13:46 신고 EDIT/DEL

      STL은 예전보다는 사용도가 많이 올라간 것 같은데 Boost는 아직도 사용을 꺼려하는 곳이 적지 않은 것 같더군요. 저는 바퀴는 새로 발명하지 않고 기존의 것이 쓸만하면 그대로 사용하고, 그 시간을 또 다른 새로운 것을 만드는데 소비했으면 합니다^^

C++, STL
한빛미디어의 한빛네트워크 사이트에 연재하던 STL 연재가 끝났습니다.




앞으로는 이 글을 토대로 완전한 글을 적는 것이 남았습니다.
현재 계획은 TR1, C++0x, Boost, ATL의 컨테이너까지 넣을 생각입니다.
by 흥배 2009. 11. 23. 09:00
  • 홍구 2010.04.28 17:39 ADDR EDIT/DEL REPLY

    좋은글 감사합니다.

  • 웬디 2010.06.13 22:55 ADDR EDIT/DEL REPLY

    안녕하세요~좋은글 잘 읽고 있습니다만... (2-2) 싱글톤 템플릿 클래스 부분의 소스중에서 궁금한점이 있어서 이렇게 찾아왔습니다. 타이핑 해가면서 공부중인데요 template <typename T> T* MySingleton ::_Singleton = NULL; 이부분에서 T* MySingleton<T> 라고 해줘야 에러가 안나는데요. 그리고 class MyObject : public MySingleton 템플릿 클래스 상속을 받을때도 : public MySingleton 다음에 자료형을 입력해줘야 에러가 안나는거 같은데 제가 템플릿 공부한지 얼마 안되서 머가 맞는건지 잘 모르겠내요;;
    올려주신 소스를 카피해서 컴파일해도 에러가 발생하는데요;; 제가 잘못한건지 아니면 올려주신 소스상에 문법적으로 빠진 부분이 있는건지요. 답변 부탁드릴게요!

    • 흥배 2010.06.14 00:00 신고 EDIT/DEL

      제가 적은 글이 웹에 올라갈 때 제대로 올라가지 못한 부분이 있습니다. 한빛네트워크에 수정 요청을 했는데 계속 고쳐지지 않고 있네요 ;;;

  • Dowitcher 2014.12.18 11:17 신고 ADDR EDIT/DEL REPLY

    2008년에 올려주신 강의를 2014년도에 보고있습니다 :)
    구글에서 c++ map을 검색하다가 찾아오게 되었는데 정말 저같은 초보자도 STL 자료구조에 대해서 알기쉽게 적어주셨네요.
    처음부터 읽다가 너무 감사한 마음에 댓글을 씁니다. 열심히 배워서 저도 제가 가진 지식을 공유할 수 있는 개발자가 되겠습니다.
    감사드립니다!

    • 흥배 2014.12.19 11:20 신고 EDIT/DEL

      참고로 e-book으로도 나왔습니다
      http://www.hanbit.co.kr/ebook/look.html?isbn=9788979149937

C++, Set, STL
앞서 설명했던 map과 비슷하면서도 다른 set을 이번에 이야기 하려고 합니다. map 이전에는 hash_map을 설명했는데 이번에 이야기할 set과 여러 부분에서 중복되는 부분이 있고, 저는 현업에서 set을 사용하는 경우가 거의 없어서 이번에는 내용이 길지 않을 것 같습니다.

8.1 set 이란

set은 원하는 key를 신속하게 찾고, 또 이 key가 정렬되기를 원할 때 사용합니다.(여기서 말하는 key라는 것은 저장할 자료를 말합니다). map과 비슷하지만 다른 점은 map은 key와 값이 한 쌍으로 저장하지만 set은 key만 저장합니다. set도 map과 같이 key를 중복으로 저장할 수 없습니다. 만약 key를 중복으로 사용하고 싶다면 multiset을 사용해야 합니다. 사용방법은 set과 거의 같습니다. set은 map과 같이 이진 탐색 트리 자료구조를 사용합니다.

8.2 set을 사용할 때

앞서 이야기 했듯이 set은 자료를 저장할 때 내부에서 자동으로 정렬하고, map과 다르게 key만 저장합니다.

set은 아래 조건일 때 사용하면 좋습니다.
  1. 정렬해야 한다.
  2. key가 있는지 없는지 알아야 할 때
  3. 많은 자료를 저장하고, 검색 속도가 빨라야 할 때
다른 컨테이너를 설명 할 때 꽤 많은 이야기를 했는데 그동안 했던 이야기와 중복되는 것이 많고 특히 앞의 map과 비슷한 부분이 많아서 이번에는 바로 사용 방법으로 들어가겠습니다.
.........................
..............................
나머지는 여기서 보세요^^;




by 흥배 2009. 8. 27. 18:10
| 1 2 |