자유로이 날 수 있는 새가 아님을 원망하기 보다는

이렇게라도 오를 수 있는 달팽이임을 고마워 하라

작은 꽃을 무심코 짖밟았을지도 모르는 사자가 아니라

그 작은 아름다움도 크게 느끼는 달팽이임을 고마워하라

언젠간 꼭 그 높고 커다란 아름다움에 닿으리라




출처 : 해온's 싸이 (http://www.cyworld.com/nerocoke)

너를 알려라~ 해온!





출처 : 해온's 싸이 (http://www.cyworld.com/nerocoke)

너를 알려라~ 해온!


집이 아닌 다른 곳으로 가는 버스

그 막차를 앞에 두고 탈까 말까 고민했던 기억....

 

가볍게 나선 밤길의 산책중에

상념을 뿌려대던 별빛의 기억...

 

집을 나서는 추운 겨울의 아침

생각만으로도 따뜻해지던 한 사람의 기억...

 

가슴 한켠에 누구나 가지고 있을 법한 푸른 기억

 

....첫사랑의 기억...




출처 : 해온's 싸이 (http://www.cyworld.com/nerocoke)

너를 알려라~ 해온!


당신을 보고 내 마음이 또 자랐습니다.

감당 못할 또 한 잎이 텄습니다.




출처 : 해온's 싸이 (http://www.cyworld.com/nerocoke)

너를 알려라~ 해온!
난 정보통계학과를 나왔다.
따라서 전산학에 대한 지식은 거의 없는 편이지만...
아... 변명부터 하고 시작할랬는데, 생각해보니 선택교양과목으로 컴퓨터개론을 들었었다. ㅋㅋ

여튼 난 전산학 지식이 없는 건 맞다. 컴퓨터 개론 시간에는 친구들 대출 돌려막기가 유행했을 정도로 수업은 별 관심도 없었다. 그 당시만 해도 소프트웨어와 컴퓨터는 별개라고 생각했다.

리버스 엔지니어링을 해보려고 어셈블리를 좀 보다가 보니 2의 보수 얘기가 나왔다.
그래서 예전에 잠깐 들었던... 하지만 이해는 하지 못했던 내용.

그때 교수님의 설명은 이러했다.
"1은 0으로, 0은 1로 바꾸는 것이 1의 보수이고, 1의 보수에 1을 더한 것이 2의 보수입니다"
"2의 보수는 컴퓨터에서 뺄셈을 구현하는데 사용하니 알아 두셔야 합니다"

왜 1의 보수에 1을 더하는 것인지가 궁금해졌지만 책에 설명이 없어서 결국 그냥 머리속에서 지워버렸다.

그런데 오늘 어떤 블로거의 글에서 해답을 얻었다. 다음은 정확한 글은 아니고 기억에 의존해 쓴 글이다.
1byte를 예로 들면 제일 처음 1비트는 부호로 사용하고, 양수에 128가지 수, 음수에 128가지의 수를 둘 수 있다. 0은 표현해야 하니까 양수는 0부터 127까지, 음수는 -127부터 -0까지 하면 된다(1의 보수). 나는 이것이 좋지만 사람들은 0과 -0이 둘 다 사용된다는 것이 못마땅했나보다. 그래서 음수는 -128부터 -1까지로 정하였고, 양수보다 음수가 하나 더 많아졌다(2의 보수).(-128 ~ 127)
물론 더 검색을 해봤기 때문에 2의 보수가 뺄셈이 더 편해서 (계산 후 +1을 해줘야 한다) 그렇게 정했다는 글도 봤다. 하지만 나는 위 얘기가 이해가 더 잘되고 와 닿는다.

이 글 쓰면서 생각난건데, 만약 0과 -0이 따로 존재한다고 생각해보면 이건 또 zero hell 이 될 것 같다. 0과 -0은 수학적으로 같아야 하지만 비트는 분명 틀릴테니까.

뭐 이제 누가 나에게 2의 보수를 왜 쓰냐고 물어본다면 그냥 뺄셈 때문이라고 말하진 않을 것 같다.

참... 이건 내 생각인데, 2의 보수가 "2의 보수"라는 이름이 붙은 이유는 1의 보수에 1을 더하기 때문에 붙여진 이름이겠지? ㅡ_ㅡ;
윈도우에서 컨트롤의 크기 조절은 살짝 복잡하다.
내가 계속 MFC를 만지는 것이라면 항상 기억하겠지만 거의 만질일이 없다보니 계속 까먹어서...
정리해둬야지.

크기를 조절하는 데에는 4개의 함수가 쓰인다.

GetWindowRect() : 전제 화면을 기준으로 하는 위치. 즉 모니터의 좌측 상단이 (0,0) 이 된다.
GetClientRect() : 해당 윈도우의 그릴 수 있는 영역(클라이언트 영역이라고 함). 메모장이라면 텍스트를 입력하는 하얀 부분이 되겠다. 하얀 부분의 좌측 상단이 (0,0) 이 된다.
ScreenToClient() : WindowRect를 ClientRect로 바꿔주는 함수
MoveWindow() : 클라이언트 영역 내에서 윈도우(컨트롤)의 위치와 크기를 변경한다.

이 4가지를 이용하여 다음과 같이 컨트롤의 위치와 크기를 변경할 수 있다. 다음은 에디트 박스를 클라이언트 영역의 오른쪽에서 15, 아래에서 15만큼 떨어진 크기를 갖도록 하는 부분으로 OnSize에서 구현된 내용이다.

void CMyFormView::OnSize(UINT nType, int cx, int cy)
{
  CFormView::OnSize(nType, cx, cy);

  // TODO: 여기에 메시지 처리기 코드를 추가합니다.
  if(m_editLog.GetSafeHwnd() != NULL)
  {
    CRect editLogRect; // 에디트 박스의 영역
    m_editLog.GetWindowRect(editLogRect); // 에디트 박스의 스크린 영역을 구함

    // 에디트 박스의 스크린 영역을 CMyFormView 객체의 클라이언트 영역을 기준으로 변경
    ScreenToClient(editLogRect);

    CRect clientRect;
    GetClientRect(clientRect); // CMyFormView 객체의 클라이언트 영역을 구함

    editLogRect.right = clientRect.right - 15; // 클라이언트 영역의 오른쪽에 15픽셀의 공간을 둔다.
    editLogRect.bottom = clientRect.bottom - 15; // 클라이언트 영역의 하단에 15픽셀의 공간을 둔다.

    m_editLog.MoveWindow(editLogRect); // 에디트 박스의 수정된 위치를 적용함
  }
}

이거 보고 이해가 안된다면 별 수 없다.
그림까지 넣어서 설명하면 훨씬 이해가 잘 되겠지만, 지금은 회사라... ㅡ_ㅡ;;

갑자기 왠 벌레?
저놈은 벌레로 태어나 전세계 개발자들의 주둥이에 엄청난 영향을 끼친 녀석이다.
저 벌레가 Mark II 의 전선사이에 들어가 컴퓨터를 고장내지 않았다면 아마도 우리는 지금 버그, 디버깅이란 말을 사용하고 있지도 않겠지.

미국 스미소니언 박물관에 보관당하고 계신 벌레님이시다.
다음은 콘솔 프로젝트를 기준으로 작성되었다.

  1. 일반 콘솔에서 (MFC에서는 필요없음) 메모리 릭 출력하는 방법
    1. 추가해야 할 헤더

      #include <stdlib.h>

      #include <crtdbg.h>
    2. 메모리 릭 정보를 출력하고자 하는 라인에 추가할 함수나 매크로
      1) 종료할 때 Dump를 미리 지시하는 매크로 (시작시 호출)
        _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
      2) 명시적으로 메모리 릭 정보의 출력을 지시하는 함수 (종료시 호출)
        _CrtDumpMemoryLeaks();

  2. 다음 그림처럼 출력된 메모리 릭 정보에서 할당한 라인의 정보가 나오지 않을 경우

    1. malloc의 경우 (2가지 방법)
      1. 프로젝트 설정의 전처리기에 _CRTDBG_MAP_ALLOC 을 추가해준다.
        MSDN에서는 #define _CRTDBG_MAP_ALLOC 을 1번에서 추가한 헤더위에 정의하면 된다고 하였지만 실제로는 되지 않았다.
      2. 다음 코드를 추가한다.
        #if _DEBUG
        #define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
        #endif

    2. new의 경우
      1. 다음 코드를 추가한다.
        #if _DEBUG

        #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
        #endif
        malloc의 경우와 비슷하게 _CRTDBG_MAP_ALLOC_NEW를 추가하면 crtdbg.h의 인라인 operator new가 불리게 되어 항상 crtdbg.h의 operator new에서 할당받은 것으로 나오므로 쓸모가 없어진다.
  3. 2번과 같은 문제를 할당된 순서(위 그림에서 {106}, {104})를 통해 Break를 거는 방법
    1. 최대한 빨리 _crtBreakAlloc 에 값을 설정한다.
      (/MD 옵션으로 컴파일 했을 경우 {,,msvcr71d.dll}_crtBreakAllocdp에 값을 설정한다)
      _crtBreakAlloc = 104; // 104번째 동적 할당 되었을 경우 break됨
    2. _CrtSetBreakAlloc(104); 으로 설정해도 된다.
    3. 상황에 따라 할당 순서가 달라지는 경우도 많이 생기기 때문에 엉뚱한 곳을 가리킬 수 있으니 사용할 때 주의해야 한다.

위 글을 읽어보는 것도 귀찮다면 다음 두가지만 추가한다.

  • 할당 함수를 사용하기 전에 다음 코드 추가
    #include <stdlib.h>
    #include <crtdbg.h>

    // 해제가 되지 않은 메모리의 할당 위치를 알기 위해 파일과 라인넘버를 입력하는 작업
    #if _DEBUG

    #define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__)
    #if defined(__cplusplus)
    #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
    #endif
    #endif

  • 프로그램 시작 부분에 다음 코드 추가
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); // 정상 종료시 해제되지 않은 메모리 정보 출력한다
    // _CrtSetBreakAlloc(104); // 104 번째 할당 시 Break가 걸린다

다음은 예제로 사용한 소스와 실행 결과이다.


Detected memory leaks!
Dumping objects ->
c:\documents and settings\digicaps\my documents\visual studio 2005\projects\temptestcode\temptestcode\temptestcode.cpp(29) : {106} normal block at 0x003A9F40, 13 bytes long.
 Data: <Memory Leak! > 4D 65 6D 6F 72 79 20 4C 65 61 6B 21 00
c:\documents and settings\digicaps\my documents\visual studio 2005\projects\temptestcode\temptestcode\temptestcode.cpp(24) : {104} normal block at 0x003A9EF0, 13 bytes long.
 Data: <Memory Leak! > 4D 65 6D 6F 72 79 20 4C 65 61 6B 21 00
Object dump complete.
'[3428] TempTestCode.exe: 네이티브' 프로그램이 0 (0x0) 코드에서 끝났습니다.

 "CSIDL_DESKTOP                  {desktop}"

 "CSIDL_INTERNET                 Internet Explorer (icon on desktop)"

 "CSIDL_PROGRAMS                 Start Menu\Programs"

 "CSIDL_CONTROLS                 My Computer\Control Panel"

 "CSIDL_PRINTERS                 My Computer\Printers"

 "CSIDL_PERSONAL                 My Documents"

 "CSIDL_FAVORITES                {user name}\Favorites"

 "CSIDL_STARTUP                  Start Menu\Programs\Startup"

 "CSIDL_RECENT                   {user name}\Recent"

 "CSIDL_SENDTO                   {user name}\SendTo"

 "CSIDL_BITBUCKET                {desktop}\Recycle Bin"

 "CSIDL_STARTMENU                {user name}\Start Menu"

 "CSIDL_DESKTOPDIRECTORY         {user name}\Desktop"

 "CSIDL_DRIVES                   My Computer"

 "CSIDL_NETWORK                  Network Neighborhood"

 "CSIDL_NETHOOD                  {user name}\nethood"

 "CSIDL_FONTS                    windows\fonts"

 "CSIDL_TEMPLATES"

 "CSIDL_COMMON_STARTMENU         All Users\Start Menu"

 "CSIDL_COMMON_PROGRAMS          All Users\Programs"

 "CSIDL_COMMON_STARTUP           All Users\Startup"

 "CSIDL_COMMON_DESKTOPDIRECTORY  All Users\Desktop"

 "CSIDL_APPDATA                  {user name}\Application Data"

 "CSIDL_PRINTHOOD                {user name}\PrintHood"

 "CSIDL_LOCAL_APPDATA            {user name}\Local Settings\Application Data (non roaming)"

 "CSIDL_ALTSTARTUP               non localized startup"

 "CSIDL_COMMON_ALTSTARTUP        non localized common startup"

 "CSIDL_COMMON_FAVORITES"

 "CSIDL_INTERNET_CACHE"

 "CSIDL_COOKIES"

 "CSIDL_HISTORY"

 "CSIDL_COMMON_APPDATA           All Users\Application Data"

 "CSIDL_WINDOWS                  GetWindowsDirectory()"

 "CSIDL_SYSTEM                   GetSystemDirectory()"

 "CSIDL_PROGRAM_FILES            C:\Program Files"

 "CSIDL_MYPICTURES               C:\Program Files\My Pictures"

 "CSIDL_PROFILE                  USERPROFILE"

 "CSIDL_SYSTEMX86                x86 system directory on RISC"

 "CSIDL_PROGRAM_FILESX86         x86 C:\Program Files on RISC"

 "CSIDL_PROGRAM_FILES_COMMON     C:\Program Files\Common"

 "CSIDL_PROGRAM_FILES_COMMONX86  x86 Program Files\Common on RISC"

 "CSIDL_COMMON_TEMPLATES         All Users\Templates"

 "CSIDL_COMMON_DOCUMENTS         All Users\Documents"

 "CSIDL_COMMON_ADMINTOOLS        All Users\Start Menu\Programs\Administrative Tools"

 "CSIDL_ADMINTOOLS               {user name}\Start Menu\Programs\Administrative Tools"

일단은 Subversion과 Trac을 설치하고 두개를 연동시켜 두었다. 커밋할 때 티켓 번호를 입력하지 않으면 커밋이 안되도록... 과거의 경험으로 볼 때 이건 필수 기능이다.
올 초에 trac을 설치했을 때, 강제성이 없었기 때문에 사용하지 않았던 실패경험이 있거든.

뭐... 사실 SVN도 파일서버처럼 쓰고 있기는 하지만, 내가 "하대리의 하루"라는 제목으로 세미나 한 번 하면 조금은 변하지 않을까? (어느 블로그에서 본 방법)

답답하다.

여기 와서 꽤 많은 변화를 시도하였는데 먹힌 것은 Beyond Compare 밖에 없다.

뭔가 새로운 것을 도입하려고 하면 귀찮게 왜자꾸 이러냐고 한다.
trac도, SVN도, 스토리보드, 짝 프로그래밍도 모두 실패했다.
혼자 시도하고 혼자 끝났다.

개발자는 보수적이라는 누군가의 말을 뼈져리게 느꼈다.
아마 노력없이 변화되는 것이 아니라면 절대 반겨주지 않을 것이다.

버뜨! 이번 만큼은 기필코 성공하고 말겠다!
만약 많은 수정사항들을 뭉뚱그려서 업데이트 하기 위해 티켓을 만든다면 해당 티켓을 없애서 SVN 저장소에 커밋을 못하도록 아예 막아버릴테다!

근데 나... 이렇게 프로그래밍 외적인 부분만 하고 있어도 되려나?
원래 개발환경은 한번 제대로 구축되면 손이 자주 안가야 하는건데, 이게 주가 된 느낌이다.
루비도, 코코아도, 맥루비도, 핫 코코아도, 아이폰도, 안드로이드도, LiMo도... 해보고 싶은 건 천지인데, 항상 마음만이다.

그렇게 하고 싶으면 집에 가서 하면 되잖아? -_-;

+ Recent posts