Unleashed Visual C++ 5.0 정리
1998/06/21 조경민
......................................................

제 1 장
비주얼 C와 비주얼 스튜디오


[*] vc의 유용한 도구들______________________________________________

Profiler(프로파일러)는 프로그램의 성능을 검사하는 도구로 애플리케이션

의 성능에서 약점을 찾을 수 있다.



Spy++(스파이뿔뿔)은 시스템에 전달되고 있는 메세지를 보여주는 도구로서

특정 윈도우에 보내지는 모든 메세지 혹은 특정 메세지를 볼 수 있다.

또한 현재의 프로세스와 쓰레드, 그리고 쓰레드의 윈도우들의 계층 관계를

보여주며 이를 사용하여 숨겨져 있거나 스크린에서는 찾을 수 없는 윈도우

를 찾아 메세지를 추적할 수 있다.



MFC Tracer는 여러 트레이스를 켜거나 끄게 함으로써 디버깅 버전의 라이브

러리로 컴파일된 MFC애플리케이션에서 다양한 디버깅 메세지를 내보내게한다.



[*] 명령행 도구 (Command Line Tools)________________________________

c/c++ 컴파일러

cl을 사용하여 VC++컴파일러를 실행하나. 컴파일하여 링커를 싱행하여 실행

파일을 만든다.

오브젝트 파일이나 라이브러리 파일을 같이 입력한 경우에는 이것들이 함께

링커에 전달된다.

cl hello.c myfunc.obj mylib.lib



링커

linke.exe는 vc 오브젝파일인 COFF (Common Object File Format)와 32bit

오브젝트 모듈 포맷 파일(Object Module Format;OMF), 라이브러리 파일과

다른 입력 파일로 부터 Win32실행 파일이나 DLLdmf todtjdgksek.

link hello.obj



라이브러리 관리자(Library Manager)

lib.exe는 COFF 오브젝 파일의 라이브러리를 만들거나 DLL을 위한 export

파일과 import라이브러리를 만드는데도 사용된다.



프로그램 관리 유틸리티(Program Maintenance Utility)

nmake.exe(메이크)는 메이크 파일 내에 기록된 여러 파일들을 계산 컴파일

한다.

test.exe : test.obj
    link   test.obj

test.obj : test.c
    cl /c  test.c



[*] 다른 명령행 도구들_________________________________________________

rc.exe는 리소스 파일(rc)을 컴파일하여 다른 오브젝트 파일과 링크될 수 있게 한다.

bscmake.exe는 브라우즈 정보 파일(BSC)을 컴파일 시에 생성된 SBR파일로 부터 만든다.
브라우즈 정보 파일은 비주얼 스튜디오에서 검색할 수 있다.

dumpbin.exe는 COFF 오브젝트 파일의 정보를 출력한다. 바이너리 파일 출력기

aviedit.exe는 AVI파일을 간단히 편집할수 있는 도구이다.

editbin.exe는 COFF오브젝트파일의 내용을 보고 편집할 때 사용한다.



제 5 장
디버깅과 프로파일링


[*] 간단한 디버깅 기술들________________________________________________

- 메세지 박스의 사용

디버거 윈도우가 있는 것이 프로그램 실행을 방해 하거나 해결하려는 오류가

릴리즈에 있는 경우 이럴때 메세지 박스를 잘사용하여 오류를 발견할수 있다.

char tmp[100];
wsprintf(tmp,"Call x = %d,y=%d",x,y);
AfxMessageBox(tmp);


- 디버깅 출력

MFC에서 디버그 라이브러리로 컴파일되었다면 MFC의 많은 함수들이 디버깅 출

력을 내보낸다. 디버깅 출력은 CDumpContent타입의 오브저ㅔ트인 afxDump로

보내지고 이것은 비주얼 스튜디오의 출력 윈도(Output)에서 나타난다.

TRACE("call x = %d, y = %d",x,y);

TRACE보다는 TRACE1,TRACE2,TRACE3은 보다 작은 메모리와 리소스를 사용하므로

잘 이용하자. 트레이스 계열의 매크로는 애플리케이션 디버그 버전으로 컴파일

되지 않는다면 쓸모가 없다.


- 단언(Assertions)

ASEERT매크로는 정해진 조건이 만족되지 않으면 프로그램을 중단시킨다.

디버그 모드에서만 된다.

ASEERT(x >=0 );

ASSERT_VALID 매크로는 포인터가 올바른 CObject 파생 오브젝트를 가리키는

가를 확인한다.

CMyDoc* pDoc;
pDoc = GetDocument();
ASSERT_VALID(pDoc);

이 매크로는 단언이 실패한 줄의 넘버를 표시하는 메세지 박스를 실행시키고

프로그램을 중단 시킨다.


- 오브젝트 덤핑(Object Dumping)

CObject 클래스는 맴버 함수로 Dump를 가지고 있는데 이 함수는 디버깅 출력

으로 오브젝트의 내용을 출력한다. 이 기능은 CObject에서 직,간접적으로 파생된

클래스에 한에서만 사용 가능하다.

#ifdef _DEBUG
void CMyDoc::Dump(CDumpContext& dc) const
{
        CDocument::Dump(dc);
        dc << "m_x = " << m_x << '\n';
        dc << "m_y = " << m_y << '\n';
}
#endif // _DEBUG


- 메모리 누출의 감지와 CMemoryState 클래스

CMemoryState 클래스는 C++ new와 delete연산자의 잘못된 사용으로 일어난 메모리

누출을 감지 할 수 있게 한다. 현재 메모리 할당 상태를 보려면 이 클래스 오브젝을

생성하고 그것의 Checkpoint맴버함수를 호출한다. 이후에 DumpAllObjectSince맴버

함수를 실행시키면 마지막으로 Checkpoint 함수가 실행된 이후의 모든 오브젝의

내용이 덤프된다. 예로 함수 foo에 의해 할당되어 다시 반환하지 못한 오브젝트를

보려면 다음의 코드를 쓰면 된다.

CMemoryState memState;
memState.Checkpoint();
foo(x,y);
memState.DumpAllObjectSince();

만일 모든 할당된 오브젝트를 덤프가 없을 때는 DumpStatistics 맴버 함수를 사용

할수 있다. Difference 맴버 함수를 사용하여 두 메모리 상태의 차이를 조사한

후에 DumpStatics 함수를 사용한다. 이 기술은 모두 합쳐 세개의 CMemoryState 오브

젝트가 쓰인다. 처음 두 개는 메모리 상태를 덤프하는데 사용되고 세번째는 차이를

계산하는데 사용한다.

CmemoryState mmBefore,mmAfter,mmBiff;
...
mmBefore.Checkpoint();
foo(x,y);
mmAfter.Checkpoint();
if(mmDiff.Difference(mmBefore,mmAfter))
  mmDiff.DumpStatistics();

그러나 이 오브젝트는 malloc/free, GlobalAlloc/GrobalFree, LocalAlloc/LocalFree

의 잘못된 사용으로 인한 메모리 누출은 감지 할수 없다.


- MFC 트레이싱( Tacing)

MFC라이브러리의 디버깅 출력에 다양한 트레이스 메세지를 내보낸다. 이 메세지는

MFC 트레이서인 tracer.exe를 통해 켜거나 끌 수 가 있다. 이 애플리케이션은

Rools메뉴에서 실행 시킬수 있다.


- 원격 디버깅 (Remote Debugging)

원격 디버깅을 사용해서 다른 컴퓨터에서 실행되고 있는 코드를 디버그 할수 있다.

지역 컴퓨터와 원격 컴퓨터는 직렬 연결(Serial Connection)이나 랜으로 연결된다.

지역 컴퓨터는 비주얼 스튜디오의 통합 디버거를 실행시키고 원격 컴퓨터에서는

디버그 할 애플리케이션을 비주얼 씨의 디버그 모니터와 함께 실행한다.


원격디버그를 할려면 원격 컴퓨터는 비주얼 씨 디버그 모니터인 msvcmon.exe를

실행 시켜야  한다. msvcrt.dll, tln0t.dll, dm.dll, msvcp50.dll, msdis100.dll

가 설치 되어 있어야 한다. 이 파일들을 경로에 포함된 디렉토리에 추가시킨다.


먼저 원격 컴퓨터의 디버그 모니터를 실행 시키고 디버그 모니터는 설정값을 지정할

있는 다이얼로그 형태. TCP/IP 네트워크를 통해 원격 디버그를 사용할 수 있다.

원격 디버깅이 완전 설정 되면 Connect를 누른다. 이 단추를 누르면 디버그

모니터는 연결 요구를 기다리는 상태가 된다.

TCP/IP연결을 사용하면 암호를 정해야 한다. 이 암호가 지역 컴퓨터와 원격 컴퓨터가

같아야 한다.


이 디버깅의 장점은 디버거에 의해 영향받지 않는 곳에서 애플리케이션을 실행시킬수

있다는 것이다.


현장 디버깅 (Just-in-Time-Debugging)

현장 디버깅 은 익셉션으로 중단된 프로그램에 비주얼 씨 디버거를 적용시켜 문제를

파악하도록 하는 것이다. 통합 디버거에서 실행시키지 않는 애플리케이션을 디버그

하는데 유용하다. Tools메뉴의 Option명령에서 현장 디버깅을 켤수 있다. 옵션 다이얼

로그에서 Debug탭을 선택하고 현장 디버깅 체크 박스를 켠다.


제 7 장
운영체제 개요

[*] 윈도우와 메세지 ____________________________________________________

윈도우는 때로 메세지-전달 운영체제라고 불린다.

메세지는 비록 응용프로그램에 보내지기는 하지만 응용프로그램의 주소를

가지고 있지않다. 메세지는 대신 웅영체제의 기본적인 부분인 윈도우의

주소를 가지고 있다.


스레드

전형적인 Win32 응용프로그램은 기본적으로 병렬적 수행 패스인 하나이상의

스레드로 이루어져 있다. 스레드는 하나의 응용프로그램에서의 멜티테스킹으로

생각하면 된다. 예를 들어 워드에서 한 스레드는 사용자 입력을 처리하고

다른 스레드는 프린터로 문서를 출력할 수 있다.

하나의 윈도우는 항상 하나의 스레드가 소유한다. 하나의 스레드는 하나 이상아ㅢ

원도우를 가지거나 윈도우를 전혀 가지지 않을 수 있다.

Porcess1 ----> Thread1A -----> Window
       `               `-----> Window
        `----> Thread1B

Process1 ----> Thread2A -----> Window
        `----> Thread2B
        `----> Thread2C -----> Window

< 프로세스와 스레드와 윈도우의 계층 관계 >

응용프로그램은 일반적으로 각각의 수신된 메세지에 대한 DispatchMessage

라는 윈도우 함수를 초훌함으로써 메세지를 처리한다. 그리고 윈도우는

RegisterClass함수를 통해서 자신만의 윈도우 클래스를 정희할수 있다.

이 함수를 통해 프로그래머는 시스템이 제공하는 적역클래스에 전혀 속하

지 않는 윈도우 기능을 구현할수 있다. 또한 윈도우에서는 또 기존의 한

클래스에 대해 서브클래싱과 수퍼클래싱이 가능하다 서브클래싱은 하나의

윈도 클래스에 대한 윈도우 프로시저를 다른 것으로 치환하는 것을 말한다.

수퍼클래싱은 SetWindowLong(인스턴스 서브클래싱)이나 SetClassLong(전역

서브클래싱) 함수를 이용해서 윈도우 프로시저의 주소를 바꿈으로써 이루어

진다. 서브클래싱은 단지 특정 윈도우의 기능만 변하게 된다. 수퍼클래싱은

지정된 클래스의 모든 윈도우 기능에 영향을 준다.

[!] 전역 서브 클래싱은  Win32인 경우 전역 서브클래싱을 하는 응용프로그램

의 제어하에 있는 윈도우만 영향을 받는다. 그러나 16비트윈도우에서는

모든 응용프로그램의 윈도우가 영향을 받아. 그영향이 전범위에 걸친다.


수퍼클래싱은 현재의 클래스에 기반하면서 그것의 윈도우 프로시저를 유지

하는 새로운 클래스를 생성한다. 한 윈도우 클래스를 수퍼클래싱하기 위해서

응용프로그램은 GetClassInfo 함수를 이용하여 클래스 정보를 얻어내고, 얻어

낸 WNDCLASS구조를 변경하고 변경된 구조를 사용하여 RegisterClass를 호출

한다. 응용프로그램은 또한 GetClassInfo를 통해서 원래 윈도우 프로시저

주소를 얻을 수 있다. 새로운 윈도 프로시저가 처리하지 않는 메세지는 반드시

이 함수로 전해져야 한다. 비록 용어가 객체 지향 용어와 유사하지만, 윈도우

클래스의 개념을 C++의 개념과 혼동해서는 안된다. 윈도우 클래스의 개념은

윈도우가 객체지향 언어를 사용한 시기 보다 몇 년이 앞섰다.

메시지 타입

typedef struct tagMSG{
        HWND        hwnd;     // 메세지가 발생한 윈도우
        UINT        messgage; // 메세지 내용
        WPARAM        wParam;   // 메세지 부가 내용
        LPARAM        lParam;   //    "
        DWORD        time;     // 메세지가 발생한 시각
        POINT        pt;       // 메세지가 발생한 위치
}MSG;

이런 메세지들중의 대부분은 윈도우 관리 메세지 그룹이다.

이것들은 모두 WM_으로 시작하고(Window Maneger) 운영체제가 관리한다.

다른 메세지 그룹에는 에디트컨트롤,리스트박스 같은 윈도우 타입과 관

련되어 있다. 이런것은 예외없이 컨트롤 윈도우 클래스의 윈도우 프로시저

에서 처리되며 프로그래머에게는 관심없는 부분이다.

응용프로그램 또한 자신만의 메세지를 정의할수 있다. RegisterWindowMessage

함수를 호출함으로써 유일한 메세지 식별자를 얻을수 있다. 프라이비트

(Private) 메세지 타입은 응용프로그램이 부분들이 서로 통신할수 있게 한다.


메세지와 멀티테스킹

메세지 큐

16비트 윈도우에서 운영체제는 하나의 메세지 큐를 가진다 키보드나 마우스

인터럽트 같은 다양한 운영체제 이벤트로부터 만들어지는 메세지는 이 메세지

큐로 들어간다. 응용프로그램이 GetMessage나 PeekMessgae 함수를 통하여 큐

에서 다음 메세지를 꺼내가려 시도하면, 운영체제는 컨텍스트 스위치(문맥교환)

를 수행하고 큐에서 기다리는 메세지가 전해질 다른 응용프로그램을 활성화

시킨다. 그러면 큐의 상위에 있는 메세지는 꺼내지고 MSG구조를 통해 활성화된

응용프로그램에 전해진다.

응용프로그램이 GetMessage,PeekMesaage,Yield(응용프로그램이 메세지 큐를

체크하지 않고 컨트롤을 양도하는 것을 가능하게 한다.)를 호출하는 데 실패

하면 시스템은 사실상 정지한다. 메세지는 계속 메세지큐에 쌓이게 되며

메세지 큐는 크기가 정해 지므로 나중에 메세지큐 오버플로가 발생하며

사용자가 마우스를 조금 움직이는 것에도 계속 경고음이 울리는 형편없는

시스템이 된다.

Win32즉 윈도우 NT와 윈도우 95에서는 메세지큐 메커니즘이 훨씬 세련되었다.

이 선점식 운영체제에서는 더이상 경쟁적인 테스크나 스레드 사이의 질서

정연한 협력이 보장되지 않는다. 둘 이상의 스레드가 동시에 메세지 큐에

접근을 시도할수 도 있다. 게다가 테스크 스위칭이 더 이상 큐의 다음

유효 메세지에 의존하지 않음으로써 테스크가 그것의 주소를 가진 메세지만

꺼내간다는 것을 보장하지 않는다. 이것이 16비트 윈도우에서의 하나의 메세

지 큐가 Win32에서는 모든 스레드 각각의 개별 메세지 큐로 분리되는

많은 이유중 하나다.


프로세스와 멀티스레드

멀티스레드 시스템에서는 가장 적은 수행 단위가 프로세스가 아닌 스레드이다.

태스크나 스레드는 하나 이상의 스레드로 구성된다.( 일반적으로 메인 스레드

를 나타내기 위한 하나의 스레드로 구성) 새 스레드를 셋업하는데 시스템

자원 차원에서 거의 필요한 프로세스의 스레드 간의 스위칭은 시스템오버해드

가 거의 없다.

스레드 하나는 자신의 메시지 큐를 가지고 있다.운영체제는 그 스레드가

소유한 윈도우 주소를 가진 메세지를 거기에 넣어준다.

그러나 스레드는 윈도우와 메세지 처리를 위한 메세지 루프를 안 갖을수도

있다. MFC에서는 이런 스레드를 위해서 워커 스레드를 마련했다. 다른 스레드

는 사용자 인터페이스 스레드라고 한다.


윈도우 함수 호출

윈도우 시스 호출의 핵심적인 부분은 3가지 범주로 구분된다. 커널 서비스에는

에는 프로세스와 스레드 제어, 자원 관리,파일과 메모리 관리에 대한 시스템

호출이 포함된다.사용자 서비스에는 스레드,컨트롤,다이얼로그 박스,메세지등

사용자 인터페이스 요소에 대한 시스템 호툴이 포함된다. 그래픽 디바이스

인터페이스 서비스는 디바이스 독립적인 그래픽 출력 기능을 제공한다.

윈도우 시스템에는 여러 응용프로그래밍 인터페이스를 포함한다.

MAPI, TAPI, ODBC 등이 그런 것들이다.


커널 서비스

커널 서비스는 파일관리,메모리관리, 프로세스와 스레드 제어,자원 관리 범

주에 속한다. 파일관리는 저수준 ID에 대한 표준 C라이브러리 함수나 C++

의 iostream 클래스를 통해 파일 접근하는 대신에 오브젝트 라는 Win32 개념과

그와 관계된 여러 함수를 사용해야 한다. 파일 오브젝트는 C/C++라이브러리로는

접근할수 없는 파일(태스크간 통신에서 사용되는 오버랩드 IO와 메모리 맵파일)

에 접근 할수 있게 한다.

반대로 대부분의 응용프로그램의 메모리 관리 요구는 C/C++의 malloc/new연산

자로 완전히 수행된다.  Win32 응용프로그램은 이러한 함수 호출을 적당한

Win32메모리 관리 시스템호출로 번역한다.

프로세스와 스레드 관리의 가장 중요한 주의사항은 동기화(synchronization)

이다. 16비트 윈도우에서는 이문제가 나타나지 않았지만 윈95같은 선점식 멀

티태스킹 환경에서는 프로세스와 스레드는 경쟁하는 스레드의 실행 상태를 알수가

없다. 상호 의존하는 경쟁 스레드가 질서 정연하게 실행된다는 것을 보장하고

둘 이상의 스레드가 무한히중단되어 서로를 기다리는 테드락 상활을 피하기 위해

정교한 동기화 메커니즘이 필요하다.

Win32에서는 스레드가 다른 스레드에 자신의 상태정보를 주거나 코드에 민감한

영역이 재짐입실행되는 것을 막거나 다른 스레드나 오브젝트의 상태정보를

얻는데 사용하는 다양한 동기화 오브젝트를 통해 이를 해결한다.

Win32에서 많은 커널 자원은 사용자 인터페이스 자원과 구분하기 위해 커널

오브젝트로 표현된다. 이는 일반적으로 핸들을 통해 참조 가능하다.

윈도NT에서는 이 오브젝트는 또한 보안과 관련된 틀징을 가지고 있다.

예를 들어 스레드는 파일 오브젝트의 보안 특성에 상응하는 적절한 허가를

받지 않는 한 파일 오브젝트를 다룰수 없다.

또한 커널 모듈은 사용자 인터페이스 자원을 관리하는 함수도 제공한다.

아이콘, 커서, 다이럴로그 템플릿, 스트링 자원,버전 자원,단축기 테이블

비트맵과 그 밖에 사용자 정의 자원 타입이 포함된다.


사용자 서비스

윈도우 핸들, 다이얼로그 메뉴,텍스트와 그래픽 커서,컨트롤,클립보드등

이 이에 해당한다.

사용자 모듈은 또 메세지와 스레드 메세지 큐를 관리하는 함수도 제공한다.

응용프로그램은 그들의 메세지 큐의 내용을 조사하고, 꺼내와서 메세지를

처리하고, 새로운 메세지를 생성하기 위해 이런 호출을 사용한다.

보내진 메세지는 단순히 목적 윈도우를 소유한 스레드의 메세지 큐에 들어

간다. 반대로 메세지를 직접보내는 것은 목적 윈도우의 윈도우 프로시저를

호출한다. (SendMessage)


GDI 서비스

그래픽스 디바이스 인터페이스 함수는 일반적으로 디바이스 컨텍스트에 대한

기본적인 디바이스 관련 그래픽 작업을 수행한다.

컴퓨터 스크린으로 직접 출력을 위한 디스플레이 디바이스 컨텍스트와

메모리에 저장된 비트맵으로의 출력을 위한 메모리 디바이스 컨텍스트,

그리고 최종적으로 프린터 컨트롤 코드로 번역되어 프린터로 보내질 출력을

위한 프린터 디바이스 컨텍스트가 전형적인 디바이스 컨텍스트들이다.

메타파일 디바이스 컨텍스트는 GDI출력 호출을 영구히 기록하게 하는 기능

을 갖었다. 이는 OLE 오브젝트의 디바이스 독집적 표현에 있어서 중요한 역

활을 한다.즉 OLE 오브젝트를 이식 가능하게 하고 서버 응용프로그램이 없

더라도 콘테이너 응용프로그램이 자신을 디스플레이하거나 프린트 할수

있도록 해준다.


에러 보고

많은 윈도우 함수들이 에러를 리턴하는데 GetLastError함수르 통해서 얻을

수 있다. 스레드 고유의 에러값을 준이 32비트 값은 winerror.h헤더 파일이나

라이브러리 고유의 헤더파일에 정의되어 있다.

SetLastError함수를 호출함으로써 이런 에러값을 세팅할수 있다. 응용프로그램

고유 에러코드는 29번째 비트를 셋팅해야 한다. 운영체제는 이 비트를

응용프로그램 고유의 사용을 위해 남겨두었다.

'KB > MFC/Win32' 카테고리의 다른 글

윈도우프로그래밍 간략설명  (0) 2004.03.19
언리쉬드 9장 윈도우 다이얼로그 박스 컨트롤  (0) 2004.03.19
[db] sql  (0) 2004.03.19
[db] ODBC 파일 등록하기  (0) 2004.03.19
dll 설명  (0) 2004.03.19

+ Recent posts