'C | C++'에 해당되는 글 16건

  1. 2008.02.29 Num foramt 숫자의 출력 형식
  2. 2008.01.16 임시폴더, 응용프로그램 경로 알기. 윈도우 핸들로 포인터 얻기
  3. 2008.01.16 파일 관련 함수들..
  4. 2008.01.16 팝업 메뉴..
  5. 2008.01.16 OLE Drag And Drop
  6. 2008.01.16 마우스 포인터를 이용한 윈도우 핸들
  7. 2008.01.16 WaitForSingleObject 관련 스레드 다루기 1
  8. 2008.01.16 CLR 정의
  9. 2008.01.16 VS2005 Remote Dubug
  10. 2008.01.16 C++ 라이브러리를 CLI로 싸서 C# 에서 사용하기 2

Num foramt 숫자의 출력 형식

Program/C# 2008. 2. 29. 14:19
http://msdn2.microsoft.com/en-us/library/ms256225.aspx
MSDN "format-number" 검색한 주소 입니다..

예를 들어..
5 라는 숫자를 005 로 표현하고 싶다면..?
int a = 5;
a.ToString("000);

'Program > C#' 카테고리의 다른 글

전역 변수, Properties  (0) 2008.02.29
ListView 데이터 바인딩..  (0) 2008.02.29
Xml 스키마, 클래스.  (0) 2008.02.29
:

임시폴더, 응용프로그램 경로 알기. 윈도우 핸들로 포인터 얻기

Program/C | C++ 2008. 1. 16. 23:12
GetTempPath(~
GetMoudleFileName(~
CWnd::FromHandle(~

'Program > C | C++' 카테고리의 다른 글

파일 관련 함수들..  (0) 2008.01.16
팝업 메뉴..  (0) 2008.01.16
OLE Drag And Drop  (0) 2008.01.16
:

파일 관련 함수들..

Program/C | C++ 2008. 1. 16. 23:11
API

PathFileExists(~
CopyFile(~
Delete File(~
MoveFile(~
CreateDirectory(~
CreateFile(~
RemoveFolder(~
Rename(~
RenameDirectory(~
.
.
.

'Program > C | C++' 카테고리의 다른 글

임시폴더, 응용프로그램 경로 알기. 윈도우 핸들로 포인터 얻기  (0) 2008.01.16
팝업 메뉴..  (0) 2008.01.16
OLE Drag And Drop  (0) 2008.01.16
:

팝업 메뉴..

Program/C | C++ 2008. 1. 16. 22:57

# 메세지 등록
ON_WM_CONTEXTMENU()

# OnContextMenu 핸들러 구현
CMenu  main_menu;
CMenu *menu;
main_menu.LoadMenu(IDR_MENU);
menu = main_menu.GetSubMenu(3);
// IDR_MENU의 3번재 탭에 팝업 메뉴를 구성하였기 때문에 3번재 서브 메뉴를 가져옴

# 선택된 메뉴에 대한 핸들러 등록, 핸들러 구현
ON_COMMAND(IDC_DELETE_FILE,     OnMenu_Delete)

'Program > C | C++' 카테고리의 다른 글

파일 관련 함수들..  (0) 2008.01.16
OLE Drag And Drop  (0) 2008.01.16
마우스 포인터를 이용한 윈도우 핸들  (0) 2008.01.16
:

OLE Drag And Drop

Program/C | C++ 2008. 1. 16. 22:50

# MFC 기반 OLE DnD

Dnd 를 구현하기 위한 최소한의 코드를 설명하고자 한다.
우선 Ole Dnd 를 구현하기 위해 순차적인 순서를 확인해보자.

1. 이동할 Source의 선택
2. 마우스 클릭한 상태에서 마우스 이동
3. Drop 할 대상 윈도우에 마우스를 이동시킨후 Drop 실행(클릭을 풀어준다)

이과정에서 필요한 MFC 라이브러리는
 CSharedFile, COleDataSource, COleDropTarget, COleDataObject 클래스와 DROPEFFECT 구조체이다.

텍스트 에디터상에서 블록화된 텍스트를 Dnd 할 경우 1. 번 과정 이전에 Drag 할 데이터를 선택하는 작업이 필요할 것이다.
( 블록화된 데이터 렉트 안에서 마우스 클릭을 유지하는가.)
작성자가 작업했던 곳을 ListCtrl 이였으므로 이에 대한 설명을 생략하고.
앞으로의 설명은  ListCtrl에서 ListCtrl, ListBox 및 기타 다른 윈도우. 컨트롤로의 드롭이다.

# Drag가 일어나는 컨트롤 / 윈도우..
드래그가 일어나는 리스트컨트롤을 서브 클래싱 해야 한다.
서브 클래싱을 하는 이유는 OnMouseMove 이벤트를 사용하기 위함이다.
이를 서브 클래싱 하였다면 OnMouseMove 이벤트 핸들러에서부터 작업을 시작한다.

1. 마우스 버튼이 클릭된 상태인지 확인한다.
      if ( (nFlags & MK_LBUTTON) )

2. 선택된 데이터의 이동인지 복사인지 확인한다. ( 컨트롤 키보드를 통해 )
  if ( nFlags & MK_CONTROL )
   DropEffect = DROPEFFECT_COPY;
  else
   DropEffect = DROPEFFECT_MOVE;

3. Drag 임이 확인되었다면 이동시킬 데이터를 꾸려야 한다.
이단계에서 데이터를 이동시킬 타겟을 알 수 없다.

 - 데이터를 보관할 저장소 생성
   CSharedFile sf(GMEM_MOVEABLE|GMEM_DDESHARE|GMEM_ZEROINIT);

 - 저장소에 데이터 복사( 문자열을 넘겨 보겠다)
   CString DataString = "나 데이터~";
   sf.Write(DataString, DataString.GetLength() );
  ( 클립보드를 이용하여 데이터를 임시 보관 할 수 도 있겠지만.. 꽁수? )

 - 실제적으로 보내지는 데이터
   HGLOBAL hData;
   hData = sf.Detach();

4. 데이터를 보내기...
   COleDataSource Source;
   Source.CacheGlobalData(CF_TEXT, hData);
   문자열을 보내기 때문에 CF_TEXT가 된다..

5. Drag의 시작
   Source.DoDragDrop(DropEffect);
  DropEffect 는 DROPEFFECT 형 변수로써 타겟에서 이 값을 확인하여 복사인지 이동인지를 판단 할 수 있다.

# Drop Target ( 윈도우, 컨트롤 )
Drop 이벤트는 COleDropTarget::OnDrop( 생략 ~ ) 에서 핸들링 하는데..
타겟 윈도우에서 이 이벤트를 받기위해선 COleDropTarget 형 변수를 선언하고 핸들러를 재정의 하거나 DropTarget 클래스를 상속받은 클래스를 생성하여 함수를 재정의 할 수도 있다..
작성자는 CDropTarget 을 상속받는 클래스를 생성한후
OnDrop(CWnd * pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)  
함수를 재정의 할 것이며 이외에도 기타 다른 함수들을 구현함으로서 좀 더 테크니컬하게 만들 수 있을 것이다.

1. COleDropTarget 상속
   class MyDropTarget : public COleDropTarget

2. OnDrop 함수 재정의
이부분은 대상 타겟에서 마우스를 끌어다 놓았을 때 발생 하는 메세지를 처리한다.
메세지 맵에 메세지를 등록하지 않아도 될 것이다.
인자로 넘어오는 값을 살펴 보면
 pWnd : Drop 이벤트를 받은 윈도우
 pDataObject : 넘어온 데이터
 dropEffect : 드랍 효과
 point : 마우스 포인터

넘어온 데이터는 데이터를 꾸릴때와 반대의 방법으로 하면 원래 데이터를 구할 수 있다
  HGLOBAL hData = hData = pDataObject->GetGlobalData(CF_TEXT);
  CMemFile sf( (BYTE*) ::GlobalLock(hData), ::GlobalSize(hData) );
  CString DataString;
  LPSTR str = DataString.GetBufferSetLength(::GlobalSize(hData) );
  sf.Read(str, ::GlobalSize(hData) );
  ::GlobalUnlock(hData);

  이렇게 작업을 해주면 DataString 에 "나 데이터~ " 값을 확인 할 수 있을 것이다.

# 레지스트리 등록.. DropTarget 등록..
Drop의 대상이 되는 윈도우나 컨트롤(서브클래싱이 필요할 것이다)에 MyDropTarget형 변수를 선언한후.. 타겟윈도우의 생성자나 Init 부분에서
Register() 함수를 통해 Ole 를 사용함을 등록하여야 한다.
등록이 있다면 반드시 소멸또한... Revoke() 있을 것이다.
Drop 이벤트를 받는 클래스는 반드시 MyDropTarget 형 변수가 있어야 이벤트를 받을 수 있을것이다.

주절 주절 적어봤지만, 역시나 검증되진 않았다는것!!
여러가지 상황에 대한 고려와... 테크니컬한 기술들이 빠져있는 Ole Drag And Drop에 대한 맛보기 정도로 생각하면 될 것이다.

'Program > C | C++' 카테고리의 다른 글

팝업 메뉴..  (0) 2008.01.16
마우스 포인터를 이용한 윈도우 핸들  (0) 2008.01.16
WaitForSingleObject 관련 스레드 다루기  (1) 2008.01.16
:

마우스 포인터를 이용한 윈도우 핸들

Program/C | C++ 2008. 1. 16. 22:08
# WindowFromPoint
# ChildWindowFromPoint

이와 비슷하게 마우스 포인터가 해당 컨트롤에 위치하는지를 확인 할 수 있는데..

컨트롤이나 윈도위가 상속받은 함수들을 확인해보면 이와 유사한 함수들이 존재한다.

'Program > C | C++' 카테고리의 다른 글

OLE Drag And Drop  (0) 2008.01.16
WaitForSingleObject 관련 스레드 다루기  (1) 2008.01.16
CLR 정의  (0) 2008.01.16
:

WaitForSingleObject 관련 스레드 다루기

Program/C | C++ 2008. 1. 16. 09:44

WaitForSingleObject() - 보통 FindFirstChangeNotification, FindNext..., FindClose... 등과 쓰임
1. 용도

    Thread가 특정 signal이 발생할 때까지 정지해 있다가,
    signal을 받으면, 작업을 수행하고 다시 정지 상태로 돌아가게할 필요를
    자주 느끼게 된다.
    WaitForSingleObject()와 WaitForMultipleObjects()를 사용하여
    이런 need를 해결할 수 있다.
    이 함수들은 CreateEvent(), SetEvent(), ResetEvent()와 함께 사용한다.
   
2. WaitForSingleObject()

    이 함수는 하나의 Event object를 만들어 놓고,
    이 Event가 signal(SetEvent())될 때까지 기다린다.
   
    DWORD WaitForSingleObject(
      HANDLE hHandle,          // Event object handle
      DWORD dwMilliseconds // time-out interval. 단위는 millisecond
                                         // INFINITE 으로 설정할 경우, 무한정 기다린다.
    );
   
    return value:
        1) WAIT_FAILED: fail. GetLastError()로 원인을 알 수 있다. 이 경우는 logic을 빠져나간다.
        2) WAIT_ABANDONED: 이 경우는 Event object를 reset하고, 다시 WaitForSingleObject()를 호출한다.
        3) WAIT_OBJECT_0: 기다리던 Event가 signal된 경우.
        4) WAIT_TIMEOUT: time-out이 된 경우.
       
3. Sample code

    DWORD  ret;
   
    while( TRUE )  {
        ret = WaitForSingleObject( hHandle, INFINITE );
   
        if( ret == WAIT_FAILED )
            return 0;
        else if( ret == WAIT_ABANDONED ) {
            ResetEvent( hHandle );
            continue;
        }
        else if( WAIT_TIMEOUT )
            continue;
        else {
            ResetEvent( hHandle );
            // 원하는 작업을 처리한다.
        }
    }

'Program > C | C++' 카테고리의 다른 글

마우스 포인터를 이용한 윈도우 핸들  (0) 2008.01.16
CLR 정의  (0) 2008.01.16
VS2005 Remote Dubug  (0) 2008.01.16
:

CLR 정의

Program/C | C++ 2008. 1. 16. 09:44
출처 : katalog.egloos.com
C++/CLI의 설계 원리와 발전 과정

at_attach("menu_parent", "menu_child", "hover", "y", "pointer");


목차


이번 달에는 그 동안 즐겨 사용해 온 질문과 대답 형식에서 벗어나 필자가 온라인에서 찾아낸 훌륭한 문서에 대해 소개하려 합니다. 몇 주 전에 필자는 C++/CLI에서 다음과 같이 const 함수를 선언할 수 없는 이유를 묻는 질문을 받았습니다.

// reference class ref class A {    void f() const; // NOT! }; 

대답은 간단합니다. 규칙이기 때문에 어쩔 수 없다는 것입니다. CLI(Common Language Infrastructure)는 const가 무슨 의미인지도 모르는 Visual Basic®, Java, 심지어는 COBOL과 같은 다양한 언어를 지원하기 위해 설계되었습니다. 즉 CLI는 const 멤버 함수가 무엇인지 모르므로, CLI에서 이 함수를 사용할 수 없습니다.

대답을 보내고 나서 문득 기억 한구석에 있던 const와 관련하여 언어에 관계없이 컴파일러 힌트로 무언가 할 수 있었다는 내용이 떠올랐습니다. 곧바로 예전 칼럼을 찾아보니 2004년 7월에 const에 대한 질문에 대답한 적이 있었습니다. 사실 C++/CLI에서 const 멤버 함수는 선언할 수 없지만 const 데이터 멤버와 매개 변수는 가능합니다. 그림 1은 const 정적 데이터 멤버를 가진 참조 클래스를 사용하는 작은 프로그램의 예입니다. 이 프로그램을 컴파일한 다음 ILDASM을 사용하여 디스어셈블하면 다음과 같은 코드를 볼 수 있습니다.

field public static int32      modopt([mscorlib]System.Runtime.CompilerServices.IsConst)         g_private = int32(0x00000001) 

MSIL 선언자인 Modopt는 선택적인 한정자이므로 CLI 사용자는 이 내용을 이해할 수 있다면 좋고, 그렇지 않다면 그냥 무시해 버리면 됩니다. 그러나 modreq 함수는 필수 한정자이므로 반드시 이해해야 합니다. modreq의 예로는 Volatile이 있는데, volatile 참조는 운영 체제나 하드웨어, 심지어는 다른 스레드에 의해서도 언제든 변경될 수 있으므로 CLI 사용자가 Volatile을 사용하려면 Volatile이 무엇인지 알아야 합니다. 하지만 const는 선택적인 한정자입니다. 그러나 Managed Extensions는 C++ const 개체를 CLI 리터럴로 변환하는 반면, C++/CLI는 이런 작업을 하지 않기 때문에 주의해야 합니다. 공용 const 데이터 멤버를 선언한 경우 Visual Basic과 같은 언어로 작성된 클라이언트가 그 값을 바꿀 수도 있습니다. CLI 클라이언트에서 값을 바꿀 수 없도록 하려면 그림 1과 같이 개체 리터럴을 선언해야 합니다. 그렇다면 멤버 함수는 어떨까요? const 멤버 함수는 왜 지원되지 않는 것일까요?


설계 원리

필자의 대답에 대해 연구하던 중 Microsoft의 Herb Sutter가 작성한 "A Design Rationale for C++/CLI"라는 훌륭한 기사를 찾아냈습니다. Herb는 C++/CLI의 설계자 중 한 사람입니다. 이 문서(앞으로는 '설계 원리'로 부름)는 Herb의 블로그에서 찾을 수 있습니다. URL이 너무 길고 복잡하므로 검색 엔진에서 "C++/CLI Rationale"을 찾아보기 바랍니다. 제목이 말해 주듯이 이 문서는 C++/CLI에 대한 대부분의 의문에 대해 설명해 주고 있습니다. 이 문서는 “왜 C++를 확장했는가”라는 질문에서 const 함수에 대한 필자의 궁금증에 이르기까지 모든 것을 답해 줍니다. C++/CLI의 설계 배경과 근본적인 개념을 알고 싶다면 이 문서를 반드시 읽어볼 것을 권합니다. 여기서는 모두 소개할 수 없으므로 중요한 부분만 요약해서 소개하겠습니다.

일단 가장 중요한 질문, 왜 C++를 확장했는가에 대해 알아보겠습니다. 간단하고 분명한 대답은 “C++를 CLI의 중요한 언어로 사용하도록 하기 위해서”입니다. Microsoft® .NET Framework는 Windows® 개발의 미래이며 COBOL 조차도 CLI를 지원합니다. 즉, C++/CLI는 C++의 지속적인 성공을 위해 설계된 것입니다.

하지만 왜 굳이 C++를 사용할까요? ^ 또는 %와 같은 새로운 개념도 있고 ref, value, property와 같은 새 키워드도 있는 다른 언어를 확장하면 어떨까요? 사실 다른 방법은 없었습니다. '설계 원리'에서는 Bjarne Stroustrup의 말을 인용해 이러한 질문에 대답하고 있습니다. "우리가 필요한 거의 모든 개념은 기본 속에서 찾을 수 있습니다. 라이브러리를 사용하는 방식이 정말로 실현 불가능할 경우에만 언어 확장 방식을 사용해야 합니다."

평범한 C++ 코드의 경우 CLI를 대상으로 하는 것은 다른 프로세서를 위한 컴파일러를 만드는 것과 같습니다. 여기까지는 문제가 없으나 CLI는 특별한 코드 생성이 필요한 새로운 개념을 도입했으며 이는 C++에서 간단히 표현할 수 있는 것이 아닙니다. 예를 들어 속성에는 특별한 메타데이터가 필요합니다. 라이브러리나 템플릿 없이 속성을 구현할 수는 없습니다. '설계 원리'에서는 속성을 비롯하여 다른 CLI 기능을 대체할 수 있는 몇 가지 구문을 소개하고 있으며, 이러한 구문이 결국 왜 사용될 수 없었는지에 대해서도 설명하고 있습니다.

Back to top

Managed Extensions의 쇠퇴

'설계 원리'에서는 또한 Microsoft에서 Managed Extensions를 더 이상 사용하지 않기로 결정한 이유에 대해서도 설명하고 있습니다. Managed Extensions에서 관리된 개체와 네이티브 개체 모두에 *를 사용한 것은 C++와 CLI를 통합하기 위한 영리하고 용감한 시도였지만, 참조와 네이티브 개체의 중요한 차이점이 분명치 않았습니다. 이러한 두 종류의 포인터는 같아 보이지만 동작은 다릅니다. 예를 들어 소멸 구문, 복사 생성자, 생성자/소멸자 내에서의 가상 호출 등이 모두 포인터가 가리키는 개체가 무엇인지에 따라 다르게 동작하며 이는 끔찍한 일입니다. '설계 원리'에서는 "불필요한 차이점을 감추는 것도 중요하지만 필요한 차이점은 반드시 공개해야 한다.”고 설명하면서 다시 Bjarne의 말을 인용하고 있습니다. "중요한 작업은 반드시 눈에 띄어야 합니다." 네이티브 클래스와 관리되는 클래스는 근본적으로 다른 것이므로 무시하기 보다는 그 차이점을 부각시키는 것이 나은 방법일 것입니다. 이를 위해 여러 가지 메커니즘이 고안되고 버려졌으며, 결국 C++/CLI 팀은 gcnew, ^(핸들) 및 %(참조 추적)와 같은 개념을 도입했습니다. 이렇게 관리되는 클래스와 네이티브 클래스를 분리하면 뜻밖의 효과도 누릴 수 있습니다. 예를 들어 gcnew 연산자를 사용하여 관리되는 개체를 할당하면 언젠가 관리되는 힙에서 네이티브 클래스가 할당되고, 그 반대 방향의 작업도 가능할 수 있다는 가능성을 열어두게 됩니다.

Managed Extensions는 왜 __gc나 __value와 같이 보기 흉한 밑줄 키워드를 사용하는지 궁금했던 적이 있습니까? 이는 Managed Extensions가 C++ 표준을 엄격하게 따르기 때문입니다. C++ 표준에서는 새 키워드가 필요하다면 이름 앞에 밑줄 두 개를 붙이라고 지정하고 있습니다. 꼭 그래야 할까요? Microsoft에서 __gc라는 키워드를 도입했을 때, __에 대해 프로그래머들은 강력한 항의를 보냈습니다. 뭉치면 못할 것이 없습니다. 밑줄 문자 밖에는 잃을 것도 없습니다. 밑줄을 사용하면 코드를 읽기 어려울뿐더러 마치 어셈블리 프로그램과 같이 난해하게 보이기도 합니다. 결국 C++/CLI에는 밑줄이 없는 ref 및 value가 추가되었습니다. C++에 새 키워드를 추가한 셈이지만 표준을 따르지 않아도 문제될 것은 없습니다. Bjarne은 이렇게 말합니다. "제 경험에 따르면 사람들은 자신이 고안한 매우 복잡하고 어려운 개념을 사용하기 위해 새 키워드를 만드는 것을 지나치게 좋아합니다. 그 결과, 점차 새로운 키워드들은 우리가 흔히 사용하는 용어와는 전혀 다르게 변해가고 있습니다." 맞는 말입니다. 필자는 프로그래밍에 대한 Bjarne의 심리학적 설명을 매우 좋아합니다. C++/CLI에서 밑줄이 사라진 이유는 이것입니다. 예약된 키워드가 아닌 전후 관계에 따라 사용되는 키워드를 만듦으로써 이미 이 키워드를 변수나 함수 이름으로 사용하는 프로그램과의 충돌 문제도 방지할 수 있습니다.

궁금증이 많은 사람이라면 밑줄을 없애는 과정에서 gc가 어떻게 ref로 바뀌었는지 궁금할 수도 있습니다. '설계 원리'에서는 관리되는 클래스가 관리되는(가비지가 수집되는) 힙에 있다는 것이 중요한 것이 아니라 그 참조 구문이 중요하다고 합니다. 핸들(^)이 포인터가 아닌 참조처럼 사용되는 것도 같은 원리입니다. 이와 같이 '설계 원리'를 읽어보면 모든 것이 분명해집니다.

분명한 차이점을 드러내는 것이 중요하다면 그렇지 않은 것을 감추는 것도 중요합니다. 예를 들어 모든 연산자 오버로딩은 개체가 네이티브인지, ref인지, 또는 value인지에 관계없이 C++ 프로그래머가 예상하는 그대로 작동합니다. C++/CLI 문서에서 차이에 대해 설명한 또 하나의 예로 다음 코드를 보겠습니다.

// ref class R as local variable void f() {     R r; // ref class on stack???    r.DoSomething();    ... } 

여기서 r은 스택 개체처럼 보이지만 누구라도 관리되는 클래스는 스택에 물리적으로 넣을 수 없다는 것을 알 것입니다. 관리되는 클래스는 관리되는 힙에 할당해야 합니다. 그렇다면 무슨 일이 벌어질까요? 컴파일러는 이 코드를 다음과 같은 의미로 해석하게 됩니다.

// how the compiler sees it. void f() {     R^ r = gcnew R; // allocate on gc heap    try    {       r->DoSomething();       ...    }    finally    {       delete r;    } } 

결과적으로 개체는 실제 스택에 할당되지 않습니다. 여기서 중요한 것은 로컬 변수 구문이 모든 C++ 프로그래머가 예상하는 방식으로 작동한다는 점입니다. 특히 f를 벗어나기 전에 r의 소멸자가 호출되는 것은 C++/CLI에서 결정적 소멸을 복원한 이유와 같은 이유로 설명할 수 있습니다. 소멸을 위해 모든 C++ 프로그래머가 알고 사용하는 것과 동일한 구문을 따르고 있다는 것입니다. 비결정적 소멸은 Managed Extensions의 기능 중 최악의 것으로, C++/CLI는 이 문제를 해결하기 위해 소멸자를 Dispose에 매핑하고 종료자를 위한 특별한 구문인 !를 도입했습니다. 참조 개체가 사용하는 메모리는 가비지 수집기가 활동하기까지는 그대로 남아있게 되지만 그리 큰 문제는 아닙니다. C++ 프로그래머에게는 필요할 때 소멸자가 실행되는 것이 중요하지, 개체가 파괴될 때 메모리를 회수하는 것이 중요하지는 않습니다. C++ 프로그래머는 파일 핸들, 데이터베이스 잠금과 같이 메모리 리소스가 아닌 개체를 초기화/해제하는 데 생성/소멸 패턴을 자주 사용합니다. C++/CLI를 사용하면 참조와 네이티브 클래스에 대해 여러분이 기대하는 방식 그대로 친숙한 생성/소멸 패턴을 사용할 수 있습니다. 결국 이와 같은 이유로 인해 Microsoft는 Managed Extensions의 문제를 인식하고 이를 수정하는 작업을 포기하게 된 것입니다.

Back to top

미래에 대한 기대

'설계 원리'의 흥미로운 단원 중에 "Future Unifications(미래의 통합)"이라는 부분이 있습니다. 이 단원에서는 C++/CLI가 미래에 어떤 방향으로 발전할지에 대해 약간의 힌트를 주고 있는데, 예를 들어 지금은 관리되는 클래스에서 네이티브 클래스를 파생할 수 없고 그 반대로도 마찬가지지만 “기본” 클래스를 데이터 멤버로 추가하고 컨테이너 인스턴스를 호출하는 것만 담당하는 통과 래퍼를 만들면 같은 결과를 만드는 해결책을 구현할 수 있습니다. 아주 좋은 방법으로 보이며 컴파일러가 이러한 작업을 지원하지 못할 이유가 없어 보입니다. 컴파일러는 모든 CLI 부분을 포함하는 하나의 CLI 개체와 모든 C++ 부분을 포함하는 하나의 C++ 개체로 구성된 혼합된 개체를 만들어 사용할 수 있을 것입니다.

이에 대한 흥미로운 일화도 소개되어 있습니다. '설계 원리'의 저자가 이러한 혼합 클래스에 대한 아이디어를 Bjarne Stroustrup에게 처음 보여주었을 때, Bjarne은 서재로 가서 책을 펴 보여주면서 “C++에서 개체를 단일 메모리 블록에 연속해 저장할 필요는 없다.”고 말했다고 합니다. 이때까지 누구도 비연속적인 개체의 이점을 알지 못했으며 .NET과 CLI가 개발될 것이라고 예상하지도 못했습니다. 비연속이라는 문을 열어야 한다는 Bjarne의 고집이 결국 혼합된 개체를 가능하게 만든 것입니다. C++/CLI의 나중 버전에서 이러한 기능을 보게 되도 놀라지 마십시오. 여기서 주는 교훈은 여러분이 새 언어나 복잡한 프로그램을 설계하여 계속 사용될 것으로 기대한다면 단지 약간의 편의를 위해 절대 불필요한 가정을 해서는 안 된다는 것입니다.

이 밖에도 '설계 원리'에서는 재미있는 몇 가지 사실도 소개하고 있습니다. Microsoft가 C++/CLI의 원래 내부 이름으로 사용한 것은 MC^2였다고 합니다. M은 “관리되는”의 의미, C는 C++를 의미하며 ^2는 앨버트 아인슈타인의 공식에서 차용한 것입니다. 하지만 결국 이름이 너무 장난스럽다는 이유로 채택되지 못했습니다. 필자도 동의하는 부분입니다. MC^2라는 이름을 그대로 사용했다면 아마도 받아들이기 힘들었을 것입니다. 이름을 C++/CLI로 결정한 데는 Bjarne이 C++의 이름에 대해 말한 것과 같은 이유가 있었습니다. Bjarne은 "이름을 C++라고 정한 것은 짧고, 쉽게 해석이 가능하며 ‘부수적인 C’와 같은 형식이 아니었기 때문입니다”라고 말했습니다. C++/CLI 역시 C++를 먼저 넣고, "부수적인 C++"라는 표현을 피한 것뿐입니다.

'설계 원리'에서는 속성, gcnew, 제네릭 및 const 등의 다른 C++/CLI 확장 기능에 대한 설명과 더불어 마무리에는 유용한 질문과 대답 단원을 소개하고 있습니다. 자세한 내용은 '설계 원리'를 다운로드하여 읽어보십시오. Const에 대해 다시 얘기해 보겠습니다. C++/CLI는 왜 const 데이터는 허용하면서 const 함수는 허용하지 않는 것일까요? 간단히 얘기하면 CLI는 modopt/modreq를 함수에 직접 넣는 것을 허용하지 않기 때문입니다. 이 정보를 메타데이터에 인코딩하는 방법이 있기는 하지만, 아직 테스트되지 않았습니다. 그리고 '설계 원리'에서는 언젠가 이러한 기능이 추가될 것이라고 조심스럽게 시사하고 있습니다.

Back to top

프로그래밍의 진화

C++/CLI는 C++를 CLI의 중요한 언어로 만들었으며 '설계 원리'를 읽어보면 이러한 결정에 대해 작은 의심도 없었음을 알 수 있습니다. C++는 아직도 시스템 프로그래밍 분야에서 최고의 언어이며, 이는 다른 어떤 언어보다도 CLI에 직접적으로 액세스할 수 있고 아직까지도 널리 사용되는 예전 Win32® API를 호출해야 할 경우 C로도 확장될 수 있기 때문입니다.

C++/CLI가 얼마나 중요하며 무엇을 나타내는지 이해하기 위해서는 현재 우리가 프로그래밍의 진화 단계에 어느 지점에 있는지 생각해 보아야 합니다. 간단하게 이러한 내용에 대해 살펴보겠습니다. 예전에는 프로그래머가 토글 스위치를 사용하여 프로그램을 작성했습니다. 여기서 발전한 것이 종이 테이프였고, 각 컴퓨터가 고유한 “기계” 언어를 가지는 단계로 발전했습니다. 컴퓨터가 진화함에 따라 프로그래머도 이러한 새 기계를 대상으로 하는 프로그램을 만들어야 했고, FORTRAN, BASIC, C와 같은 고급 언어가 개발되었으며 고급 언어를 각 컴퓨터에 대한 명령으로 변환해 주는 “컴파일러”가 사용되기 시작했습니다. 그림 2에서 이러한 과정을 보여 줍니다. 이제 프로그램을 만들어 컴파일하면 다른 컴퓨터에서 쓸 수 있게 된 것입니다. C가 시스템 프로그래밍을 위한 최적의 언어로 선택된 이유는 “고급 언어 중 가장 저급 언어”였기 때문입니다. 이는 사람이 사용할 수 있는 언어 중 가장 기계와 친숙한 언어라는 의미입니다. 근래에 사용되는 대부분의 운영 체제는 C로 작성되었으며 성능이 중요하고 하드웨어 조작이 필요한 일부분만 어셈블리 언어로 코딩되어 있습니다.

오랜 세월 후에 C를 개선하여 개체 지향 방식 등 많은 새로운 기능을 도입한 C++가 등장했습니다. Bjarne은 이렇게 말했습니다. "C++는 저자나 그의 친구들이 어셈블러, C 또는 다양한 근래의 고급 언어를 사용해 프로그래밍할 필요가 없도록 하기 위해 설계되었습니다. C++의 주 목적은 모든 프로그래머가 좋은 프로그램을 편하고 즐겁게 작성할 수 있도록 하는 것입니다." C++는 훌륭한 언어이지만, 고급 언어는 서로 호환되지 않는 경우가 많습니다. C++에서 코드를 작성하면 이를 BASIC과 같은 다른 언어에서 사용할 수 없으며, 가능하다 해도 상당한 어려움이 따릅니다. 각 언어는 각자 고유한 영역 내에서 처리되기 때문입니다. 이러한 특징은 독립 실행형 응용 프로그램에는 문제가 없지만 응용 프로그램이 보다 복잡해지고 환경이 분산되면서 공유 코드에 대한 필요성이 대두되기 시작했습니다. 결국 프로그래머는 완벽히 캡슐화되어 재사용이 가능한 구성 요소를 원하게 된 것입니다. 이러한 구성 요소를 사용하면 각 조각을 만들어 결합하는 것으로 응용 프로그램을 만들 수 있을 것이며 모든 조각이 같은 언어로 작성될 필요도 없을 것입니다.

이러한 다양한 구성 요소를 통합하려는 시도는 몇 년에 걸쳐 진행되었습니다. 처음에는 C 런타임이나 printf와 같은 라이브러리를 사용한 언어가 등장했고, Windows가 사용되면서 메모리 절약을 위한 DLL의 지연 로딩(DLL에 Dynamic이란 이름이 사용된 이유임)이 제공되었습니다. 또한 Visual Basic이나 COBOL과 같은 언어에서 가져오기 구문을 사용하여 컴파일러가 C와 연계된 호출을 DLL에 보내는 방식으로 DLL 사용이 가능해짐으로써 언어의 상호 운용성이 증대되는 효과가 있었습니다. 하지만 응용 프로그램과 DLL의 연결은 너무 강했으며 부서지기도 쉬웠습니다. 각 응용 프로그램은 DLL의 각 항목에 대한 이름과 서명을 알아야 했고 DLL에서 응용 프로그램으로의 호출은 함수 포인터를 콜백으로 전달해야 했으므로 상당히 귀찮은 일이었습니다. 때문에 프로그래머들이 VBX를 개발했고, 이 것이 OCX를 거쳐 COM으로 발전했습니다. 다행히도 COM은 언어 중립적인 것으로, COM에는 “형식 라이브러리”가 있어 연결 시 함수 이름을 알 필요가 없고 런타임에 문의하는 방식이 가능했습니다. COM은 상당히 유용하지만 프로그래밍이 매우 어렵다는 단점이 있습니다. 아이러니하게도 C++에 기반을 두고 있으면서도 C++에서 프로그래밍하기가 가장 어렵습니다. COM에는 다른 문제도 있습니다. 너무 저급 언어이며 보안이나 메모리 관리에 대한 기능이 빈약하다는 것입니다.

Back to top

최종 목표

현재는 2007년이며 우리에게는 .NET Framework와 그 표준 부속물인 CLI가 있습니다. CLI는 프로그래밍 언어와 컴퓨터 사이에 새로운 추상 계층을 삽입하여 재사용성 문제를 완전히 다른 방법으로 해결하였습니다. 이제 시스템 명령을 생성하는 대신 컴파일러는 MSIL 코드를 생성하며 CLI 가상 시스템/JIT(just-in-time) 컴파일러가 이를 즉시 기계어 코드로 컴파일합니다. 가상 시스템(Virtual Machine, VES 또는 Virtual Execution System)은 컴퓨터를 위한 추상 계층을 제공합니다. 가상 시스템은 새로운 개념이 아니라 사실 오랫동안 사용되어 왔습니다. Pascal이나 ZIL(필자가 한때 몸담았던 Infocom이란 회사에서 게임 개발을 위해 내부적으로 사용하던 언어, Zork Implementation Language의 약자임)과 같은 언어는 고급 언어를 P-코드(또는 Z-코드)로 컴파일하여 가상 시스템에서 해석하는 방식을 이미 사용하고 있었습니다. 하지만 CLI는 모든 언어가 사용할 수 있는 공용 가상 시스템(CLI에서 C가 의미하는 부분)을 제공한다는 점이 다릅니다. CLI는 클래스, 속성, 상속성, 리플렉션과 같은 기본적인 개념을 지원합니다. VES/VM는 메모리 관리와 보안 기능도 제공하므로 프로그래머는 악의적인 바이러스에 문을 열어 주는 버퍼 오버런이나 기타 버그를 걱정하지 않아도 됩니다. .NET Framework와 CLI가 널리 사용되면서 Visual Basic, Fortran, COBOL, C#과 같은 고급 언어는 점차 그 경계가 사라지는 분위기이며, 클래스, 상속성, 멤버 함수 등의 CLI 기반 개념을 지원해야 하기 때문에 C++ 역시 그 영향을 받고 있습니다. 각 언어는 여전히 독자적인 영역을 가지고 있으므로 프로그래머가 자신의 도구를 .NET Framework을 사용하도록 바꿀 필요는 없으며 몇 가지 새로운 개념만 배우면 됩니다.

이제 프로그래머는 원하는 언어를 선택하여 클래스를 작성할 수 있으며 언어에 관계없이 다른 프로그래머가 작성한 클래스를 사용할 수도 있습니다. 어떤 언어를 사용해도 모든 구성 요소를 프로그래밍할 수 있고, 약간의 프로그래밍 노력만 거치면 모든 구성 요소가 매끄럽게 서로 연결됩니다. 또한 CLI의 보안, 가비지 수집 등 인프라 기능(CLI에서 I가 의미하는 부분)의 혜택을 받을 수 있습니다. 이후에 Microsoft에서 새로운 CLI 기능을 추가하면 모든 언어가 그 혜택을 받을 수 있을 것입니다. Windows Vista™와 .NET Framework 3.0(10,000개의 새 클래스와 더불어 Windows Presentation Foundation, Windows Communication Foundation, Windows Workflow Foundation 및 Windows CardSpace™와 같은 새로운 기술이 연계되어 있음)이 개발되면서 Windows는 CLI 클래스로서 다시 만들어지고 있습니다. 이제는 재사용 가능하고, 언어 중립적이며 상호 운용이 가능한 구성 요소라는 목표에 도달한 것으로 보입니다. 이는 매우 큰 패러다임의 변화로, 전진적인 진화를 거쳐 놀라운 수준에 이른 것입니다. 이제는 프로그래밍이 아주 쉬워지고 있습니다.

이러한 모든 사항을 곰곰이 생각했을 때 C++가 새로운 세계에 적응하는 것은 당연한 일로 생각됩니다. C++/CLI이 등장한 이유가 바로 이것입니다. C++/CLI가 없다면 C++는 Windows 프로그램에 사용할 수 없는 유일한 근대 프로그래밍 언어로 남았을 것입니다. 또는 점차 그 수명을 다하여 역사의 변두리로 밀려났을 수도 있습니다. 하지만 C++/CLI가 있기에 그런 일은 일어나지 않습니다. C++를 좋아하는 필자와 같은 프로그래머는 걱정 없이 계속 사용해도 됩니다. 그림 2는 프로그래밍 언어의 패러다임 변화와 그 속에서 C++가 차지하는 위치, 그리고 "/CLI"가 없다면 어떨지를 간략하게 보여 줍니다.

그림 2 프로그래밍의 진화 과정
그림 2 프로그래밍의 진화 과정 (더 크게 보려면 이미지를 클릭하십시오.))
Back to top

작별 인사

이제 작별 인사를 하려고 합니다. 그 동안 필자가 기고해온 C++ At Work 칼럼이 이번 호를 마지막으로 여러분 곁을 떠납니다. 많은 칼럼이 중단되는 와중에서도 그 동안 꽤나 오래 이 칼럼을 기고해 온 것을 자랑스럽게 생각합니다. 칼럼이 중단되는 것은 Microsoft나 MSDN®Magazine에서 C++의 위상이 약해진 것 때문은 아니며, 14년간에 걸친 164개 칼럼(이번이 165개 째)을 기고하면서 필자가 많이 지쳤기 때문입니다. 재미있는 일화를 하나 소개하면, 편집장인 Josh Trupin은 필자를 "MSDN Magazine의 Cal Ripken"이라고 부르기도 했습니다. 필자는 야구 팬은 아니지만(축구를 더 좋아합니다) Cal Ripken이 누군지는 압니다. 그래서 Cal이 몇 경기나 출장했는지 웹에서 검색해 보았더니 2,632 경기였습니다. 그리고 그의 이력에서 "많은 팬들은 Cal이 충분히 휴식을 취했다면 더 나은 플레이어가 되었을 것이다."라고 말한 내용도 보았습니다. 필자에게도 해당되는 말이라 생각합니다. 하지만 이것이 필자가 다시는 MSDN Magazine에 기고하지 않을 것임을 의미하지는 않습니다.

칼럼을 마치면서 그 동안 필자의 많은 오류와 실수를 지적해주고 격려를 통해 힘을 준 많은 독자들에게 감사의 말을 전하고 싶습니다. 어떤 독자는 필자가 칼럼을 게시하기 전에 솔루션을 테스트하는 수고를 해주기도 했습니다. 또한 그 동안 함께 일해온 MSDN Magazine의 많은 동료들에게도 감사의 말을 전합니다. 과거에서 현재로 순서 없이 나열해보면 Steve, Josh, Joanne, Eric, Etya, Terry, Laura, Joan(두 명 모두), Nancy, Val, 그리고 Milo가 떠오릅니다. 빠진 사람이 있는지 모르겠네요. 이들은 그 동안 필자를 여러모로 많이 지원해 주었으며 다양한 분야와 내용의 집필이 가능하도록 필자에게 자유로운 공간을 허락해 주었습니다. 그 중에서도 특히 Gretchen Bilson에게 감사하고 싶습니다. 몇 년 전 이미 MSDN Magazine을 떠난 그녀는 MSDN MagazineMicrosoft Systems Journal이던 1993년에 필자를 고용한 고마운 분입니다.

여기까지입니다. 하지만 영영 떠나는 것은 아닙니다. 아놀드 슈왈츠제네거가 말했듯이 저는 돌아올 것입니다. 즐거운 프로그래밍을 계속하시기 바랍니다.

:

VS2005 Remote Dubug

Program/C | C++ 2008. 1. 16. 09:43
VS2005에서 원격 디버깅 VS2005, .NET 2.0

2006/01/24 16:29

http://blog.naver.com/saltynut/120021507832

Written by 안재우(Jaewoo Ahn), 닷넷엑스퍼트(.netXpert)

 

고객사에서 Visual Studio 2005에서의 원격 디버깅 사용법에 대한 문의가 온 김에, 내용을 좀 정리해볼까 합니다. 원격 디버깅은 상당히 유용한 기능 임에도 불구하고, 대부분의 개발자들이 좀처럼 사용하지 않는 기능입니다. 간혹 여러가지 여건 때문에 쓸 수 없는 상황에 처해 있는 경우도 있겠지만, 대다수는 사실 '몰라서' 사용하지 못하고 있는 형편입니다.

 

이번 글에서는 원격 디버깅의 개념, Visual Studio 2005에서의 원격 디버깅에 대해 알아보고, 몇가지 주의할 사항도 함께 살펴보도록 하겠습니다.

 

원격 디버깅이란?

네이버 용어 사전 설명으로는 '원격 시스템에서 사용되는 원격 제어 콘솔에서 프로그램을 수정하고 시험하는 것'이라고 합니다. 사실 이걸로는 정확하게 무슨 말이 잘 와 닿지 않을 수 있으므로, 좀 풀어서 설명해보도록 하죠.

 

일반적으로 우리가 디버깅을 시작하려면 개발툴(Visual Studio)에서 디버그 모드(F5 키)로 애플리케이션을 시작하게 됩니다. 디버그 모드로 애플리케이션을 구동하면, 당연히 애플리케이션을 호스트하는 프로세스가 만들어질테고, 프로세스는 자신이 필요한 모듈(.exe, .dll)을 로드하게 됩니다. 이 때, 디버그 모드에서는 모듈에 해당하는 디버그 심볼 파일(.pdb)을 같이 로드하게 됩니다.

 

그런데, 디버그 모드로 '시작'한다는 의미는 애플리케이션을 처음부터 새로 시작한다는 의미입니다. 그리고 디버그 모드를 '종료'하면 애플리케이션도 같이 종료되어 버립니다. 당장 코드를 개발 중일 때는 이러한 방법으로 디버깅을 할 수 있겠지만, 항상 개발을 하다보면 멀쩡하게 잘 돌아가던 애플리케이션에서 말썽이 생기는 경우가 많습니다. 즉, 이미 돌아가고 있는 애플리케이션에 대해 디버깅을 할 수 있는 방법은 없느냐는 것이죠. 이 형태의 디버깅은 In-Process 모드와 유사하다고 볼 수 있습니다.

 

여기에서 먼저 도입된 개념이 '프로세스 디버깅'입니다. Visual Studio에서는 이미 실행 중인 프로세스에 연결(Attach)시켜서 디버깅을 수행할 수 있습니다. 디버깅을 종료하면 프로세스에서 분리(Detach)시키고, 애플리케이션 프로세스 자체는 여전히 구동되게 됩니다. 이 형태의 디버깅은 Out-Of-Process 모드와 유사하다고 볼 수 있습니다.

 

원격 디버깅은 프로세스 디버깅을 로컬 컴퓨터의 바운더리를 벗어나도록 확장한 개념입니다. 즉 원격 컴퓨터에서 실행되고 있는 프로세스를 내 로컬 컴퓨터의 디버거를 사용하여 디버깅할 수 있게 해줍니다.

 

참고로 약간 변칙적인 녀석 중 하나로 실행 중인 프로그램에 심각한 오류가 발생하면 Visual Studio 디버거를 자동으로 실행할 수 있게 해주는 Just-In-Time 디버깅도 있습니다.

 

원격 디버깅이 왜 필요한가?

로컬 디버깅의 경우, 로컬에 디버거(개발툴)가 설치되어 있다는 것을 전제로 합니다. 그러나 항상 모든 컴퓨터에 디버거(개발툴)이 설치되어 있지는 않겠죠?

예를 들어, 개발자 컴퓨터에서는 이상없이 잘 돌던 프로그램이 서버나 다른 PC에서 실행하면 문제가 발생하는 경우가 있습니다. 이런 경우, 디버깅을 해보기 위해 서버나 그 PC에 디버거(개발툴)를 설치해야 할까요?

실제로 제가 경험한 몇몇 회사에서는 서버에 Visual Studio를 설치해서 디버깅을 하는 웃지 못할 형태로 작업을 하기도 했습니다. 그런데 간혹 가다보면 Visual Studio를 설치하고 나면 제대로 동작해버리는 상황도 발생하더군요. :-)

 

전통적으로 애플리케이션을 배포하고 난 후에는 디버깅이 아닌 다른 방법을 사용해서 문제점을 추적해야 합니다. 문제점 추적 방법에 대한 다양한 개발자들의 행태(?)를 살펴보면...

 

1. 초급 : Hello World를 사랑하는 사람들(Windows 애플리케이션에서는 메시지 박스를, Java 스크립트에서는 alert를, ASP나 ASP.NET에서는 Response.Write를 찍어대는 사람들을 의미합니다)

2. 중급 : 로그 찍기. 파일, 이벤트 로그 등에 로그를 기록합니다.

3. 고급 : 기본적으로는 2번과 동일하지만, 해당 PC에 로그를 기록하는 것이 아니라 원격 로그 수집기에 로그를 기록하게 합니다. DB에 기록하거나 에러 발생 시 원격 통신으로 전송한다든지.. 성능 카운터를 활용하거나 WMI를 이용하기도 합니다.

 

로그 기록 형태가 가장 일반적이지만, 이를 통해 문제를 정확하게 파악하는 것은 디버깅에 비해 상대적으로 쉽지 않습니다. 과거에 일어난 일을 '단서'를 가지고 추정해 나가야 하기 때문입니다.

 

원격 디버깅은 이러한 상황, 즉 로그 기록만으로는 정확한 내용을 알 수 없는 경우에 사용할 수 있는 해결책 중 하나입니다. 원격 컴퓨터에 개발툴을 설치하지 않고도 원격에서 디버깅을 수행할 수 있게 해줍니다.

 

Visual Studio에서 원격 디버깅의 구동 원리

Visual Studio 2005에서 원격 디버깅이 구동되는 형태를 도식화하면 대략 다음 그림과 같습니다. 그림을 보면 이해가 갈 것이라고 판단되므로 별다른 설명은 하지 않겠습니다.

 


 

위 그림처럼 디버거 역할을 하는 로컬 컴퓨터의 VS2005와 실행 중인 프로세스(App1.exe)를 중개하는 역할은 원격 디버깅 모니터(Remote Debugging Monitor)인 msvsmon.exe가 수행합니다. 과거에 일부 원격 디버깅 시나리오에서만 유사한 역할을 수행한 Machine Debug Manager(mdm.exe)가 있었지만, 이는 더이상 사용되지 않습니다. VS2005에서는 T-SQL 디버깅을 제외한 모든 원격 디버깅 시나리오에서 msvsmon.exe가 사용됩니다. 커맨드라인의 MDM에 비해 msvsmon.exe는 GUI를 제공합니다.

 

Visual Studio에서 원격 디버깅 구성

 

위 그림을 살펴보다 보면 원격 디버깅을 하기 전에 몇가지 설정이 필요할 것이라는 점을 추측할 수 있습니다.

1. 원격 디버깅 모니터(msvsmon.exe)를 원격 컴퓨터에 설치

2. 원격 디버깅을 위한 보안 권한 설정

3. 네트워크 방화벽 설정(개인 방화벽 포함, 로컬/원격 모두)

 

1, 3번에 대한 것은 다음 MSDN 문서를 참조하기 바랍니다. 아직 한글판이 나오지 않아서 임시 URL인 것 같습니다.

http://msdn2.microsoft.com/ko-kr/library/y7f5zaaa.aspx

 

2번은 상대적으로 간단해졌는데, 과거에 권한 설정 문제가 비교적 복잡했던 것에 비해서 이제는 원격 디버깅 모니터의 Tools/Permission 메뉴에서 설정할 수 있습니다.

 

원격 디버깅 사용법

구성이 끝났으면, 이제 사용법은 간단합니다.

 

1. 원격 컴퓨터에서 원격 디버깅 모니터를 실행합니다. 다음은 실행된 모습입니다.


2. 디버깅할 대상이 되는 프로세스가 아직 실행되어 있지 않다면, 실행합니다. 이 프로세스와 관련 DLL들은 당연히 디버그 모드로 빌드되어 있어야 하며, 디버깅이 사용가능한 상황이어야 합니다.

 

3. 로컬 컴퓨터에서 VS 2005를 실행하고, 디버깅할 프로세스 및 DLL이 포함된 솔루션 또는 프로젝트 파일을 엽니다.

 

4. Debug 메뉴에서 Attach to Process를 선택합니다. Qualifier에 msvsmon.exe를 실행하고 있는 원격 컴퓨터의 이름(또는 IP)을 입력 후, 엔터 키 또는 Refresh 버튼을 누릅니다.


5. Available Processes에서 디버깅할 프로세스를 선택한 후 Attach 버튼을 누르면...

이제 디버깅 시작입니다!


원격 디버깅 시 주의할 사항

이제 사용법은 알았고, 원격 디버깅에는 몇가지 주의할 사항이 있습니다.

 

첫째, 기본적으로 원격 디버깅은 로그 추적/ 트레이스 등으로 해결할 수 없을 때 사용되는 보조적인 방법이라는 것입니다. 무조건 모든 문제를 원격 디버깅으로 해결하려고 드는 것은 바람직한 것이 아니라는 점입니다.

 

두번째, 디버깅을 하면서 브레이크를 걸었을 때, 실행 중인 프로세스 자체도 정지되어 있는 상태가 된다는 것입니다. 일반적인 애플리케이션이라면 별 상관없지만, 웹 애플리케이션처럼 서버 애플리케이션인 경우에는 문제가 심각해질 수 있습니다.

예를 들어 ASP.NET 애플리케이션을 원격 디버깅하고 있다고 가정해 봅시다. 내가 브레이크 포인트를 걸고 디버깅을 하고 있는 도중에는 ASP.NET 웹 애플리케이션이 다른 사용자의 요청에 응답할 수 없게 됩니다.

실제로 있었던 웃지못할 사건 중 하나는.. 모 고객사에서 실행 중인 서버에서 이상한 문제점이 발견되었는데, 로그나 트레이스를 하는 것이 아무것도 없어서 결국 원격 디버깅을 걸어서 문제점을 찾아 해결했습니다. 그러면서 원격 디버깅 사용법을 가르쳐 주고 나왔는데.. 그 담부터 그 개발자가 원격 디버깅을 지나치게 남발하면서 문제가 생겼습니다. 툭하면 서버가 먹통이 되어 버린다고 사용자들이 난리가 난거죠. 알고보니 개발자가 원격 디버깅을 걸어 둔 채 점심식사를 하러 갔다고 합니다. -_-;;

 

결론적으로 Visual Studio 2005에서 원격 디버깅은 보다 설정 및 사용법이 간편해지긴 했지만, 원격 디버깅은 어쩔 수 없는 경우에 사용하는 히든 카드(?)라는 점이며, 사용 시에는 가급적 빠른 시간 내에 작업을 마치는 것이 바람직하다는 것입니다.

마지막으로 원격 디버깅은 .NET으로 작성된 프로그램뿐만 아니라 Native, Script, T-SQL 등에 모두 사용이 가능하다는 점을 유념하시기 바랍니다.

'Program > C | C++' 카테고리의 다른 글

CLR 정의  (0) 2008.01.16
C++ 라이브러리를 CLI로 싸서 C# 에서 사용하기  (2) 2008.01.16
How do i use DOM xml 다루기  (0) 2008.01.16
:

C++ 라이브러리를 CLI로 싸서 C# 에서 사용하기

Program/C | C++ 2008. 1. 16. 09:43
http://blog.naver.com/limdp99?Redirect=Log&logNo=60034273093

'Program > C | C++' 카테고리의 다른 글

VS2005 Remote Dubug  (0) 2008.01.16
How do i use DOM xml 다루기  (0) 2008.01.16
BSTR 형변환  (0) 2008.01.16
: