반응형

 

 

I started to get this error after switching on (for test purposes) the new setting "Beta: Use Unicode UTF-8 for worldwide language support" in the recent Windows 10 Spring 2018 update.

The message would then appear for every file that has non-ascii characters (German Umlauts mostly in my case) and had not been stored as UTF8 before.

Short-time fix: Revert the setting to not use UTF-8 as the "Current language for non-unicode programs", but use a language with the special characters that are used in the source files.

Long-time fix: Convert all your soure files to UTF-8.

 

 

 

ref : stackoverflow.com/questions/4305923/file-load-some-bytes-have-been-replaced-with-the-unicode-substitution-character

 

File Load Some bytes have been replaced with the Unicode substitution character while loading file

I was debugging in the .Net framework source code suddenly when I stepped into a file of theirs, visual studio 2010 raised this error: File Load: Some bytes have been replaced with the Unicode

stackoverflow.com

 

 

 

ERROR: Unable to create child process

1) delete .vs folder

2)

 

 

반응형
반응형

정적코드분석

컴퓨터 소프트웨어를 분석하는 방법 가운데 하나로 그 소프트웨어로부터 만들어진 프로그램을 실제로 실행해보지 않고 분석하는 방법이다. (프로그램을 실행해보고 분석하는 방법은 동적 프로그램 분석이다). 대부분의 경우 원시 코드의 형태를 가지고 분석을 수행하지만 목적 코드의 형태를 가지고 분석하는 경우도 있다. 일반적으로 사람이 어느 정도 프로그램에 대한 이해를 바탕으로 자동화된 도구를 이용해서 분석하는 것을 정적 프로그램 분석이라고 부른다. (from wiki)

 

정적코드분석이 무엇인지 더 자세히 알아보기 위해서 c++ 언어의 정적코드분석 툴중에 하나인 cppcheck를 예를 들어 설명해 보겠다.

아래의 소스코드는 아무런 에러없이 컴파일이 잘 된다.

using namespace std;

int main()
{
    char *pBuf = NULL;
    char *pBuf1 = NULL;
    FILE *pFile;
    char szBuf[1024];
    vectorstList(4, 1);
    vector::iterator itr;

    pBuf = (char *)malloc( 1024 );
    pBuf1 = (char *)malloc( 1024 );

    pFile = popen("pwd", "r");
    if ( pFile != NULL ) {
        if ( fgets( szBuf, sizeof(szBuf), pFile ) != NULL ) {
            printf("pwd : %s", szBuf);
        }
        fclose(pFile);
    }

    stList.push_back(2);
    stList.push_back(3);

    printf("stList : ");
    for ( itr= stList.begin(); itr != stList.end(); itr++ ) {
        printf("%d ", *itr);
    }
    printf("\n");

    for ( itr= stList.begin(); itr != stList.end(); itr++ ) {
        if ( *itr == 1 ) {
            stList.erase(itr);
            itr--;
        }
    }

    printf("stList : ");
    for ( itr= stList.begin(); itr != stList.end(); itr++ ) {
        printf("%d ", *itr);
    }
    printf("\n");

    delete pBuf1;
    return 1;
}

 

 

1# g++ -g -Wall -o test test.cpp

2# ./test
3pwd : /usr/esm/src/module/test
4stList : 1 1 1 1 2 3
5stList : 2 3
6#
 
 

하지만 정적코드분석 툴인 cppcheck 를 이용하면 소스코드의 버그를 발견할 수 있다.

1# cppcheck test.cpp

2Checking test.cpp...
3[test.cpp:50]: (error) Memory leak: pBuf
4[test.cpp:49]: (error) Mismatching allocation and deallocation: pBuf1
5[test.cpp:24]: (error) Mismatching allocation and deallocation: pFile
6[test.cpp:38]: (error) Dangerous iterator usage. After erase the iterator is invalid so dereferencing it or comparing it with another iterator is invalid.
7#

 
 

cppcheck 에서 발견한 버그들은 Memory leak, Mismatching allocation and deallocation, Dangerous iterator usage 와 같은 버그들이 발견되었다.

정적소스코드 분석툴을 이용하여 모든 버그를 발견할 수는 없겠지만 프로그래머가 실수할 수 있는 부분에 대해서 다시 점검할 수 있도록 도와준다고 할 수 있겠다. 또는 미숙한 프로그래머에게는 좋은 학습도구가 될 수 있을 것으로 보인다.

[참고]
위키피디아 : List of tools for static code analysis
위키피디아 : cppcheck



http://godway1225.blog.me/80120146362


반응형
반응형

http://cafe.naver.com/windev/51


윈도우 심볼 다운로드


디버깅 시 콜스택을 보면 윈도우 모듈에서 에러가 발생한 경우 함수의 이름이 아니라

모듈에서의 주소로 표시됩니다. 사실 그 주소만 봐서는 구체적으로 어떤 함수인지 알기 어렵습니다.

그러나 윈도우 심볼을 설치하시면 그러한 주소만 나오는 것이 아니라 함수 이름으로 표시됩니다.

그러므로 자신이 사용하는 운영체제에 맞는 윈도우 심볼을 설치해 두고 개발하는 것이 편합니다.

 

아래 링크에서 윈도우 심볼을 받을 수 있으니 참고하시기 바랍니다.

http://www.microsoft.com/whdc/devtools/debugging/symbolpkg.mspx

 

 

심볼을 설치하여 등록한 경우 Call stack에서 나타나는 모양은 다음과 같이 달라지게 됩니다.

(※ 심볼을 등록하려면 심볼이 설치된 폴더를 "Visual Studio > 도구 > 옵션 > 기호"에 등록해주시면 됩니다.)







그런 다음 도구->옵션->기호 로가서 심폴이 설치된 절대경로를 포함한다


window7이고 기본 상태의 경우 C:\Symbols 임



반응형
반응형




http://blog.naver.com/tipsware/100149886155






먼저 오류번호 앞에 C 가 붙어 있으면 컴파일 오류코드라는 뜻이고 LNK 가 붙어 있으면 컴파일은 성공했지만 링크(link) 작업을

하다가 생긴 오류코드라는 뜻입니다.

 

"소스파일(*.c, *.cpp)"  ->  컴파일  ->  "목적파일(*.obj)"  ->  링크  ->  "실행파일(*.exe)"

 

 

1. C2086 오류코드

 

    C/C++ 언어에서는 전역변수를  동일한 이름으로 중복해서 선언할수 없기 때문에 이와같은 컴파일 오류가 발생합니다.

   (  g_data 전역변수를 중복해서 선언하여 발생한 오류 )

    이런경우는 대부분 전역변수를 많이 사용하는 프로그래머들이 실수로 이름을 중복 사용해서 발생하며 중복된 이름을

    다른 이름으로 변경하여 오류를 수정해야합니다.

 

    int g_data;
    int g_data;   // error C2086: 'g_data' : redefinition

 

    void main()
    {

     }
 

 

2. C2084 오류코드

    

    C 언어에서는 함수를 동일한 이름으로 중복해서 정의할수 없기 때문에 이와같은 컴파일 오류가 발생합니다. C++ 에서는

    함수의 오버로딩을 사용하여 동일한 이름을 가진 함수를 정의할수 있지만 아래와 같이 동일한 이름과 동일한 매개변수 구조를

    가진 경우에는 오버로딩이 적용되지 않기 때문에 아래와 같이 오류가 발생합니다.

    ( Test 라는 함수가 같은 소스내에 중복해서 정의 되었기 때문에 발생하는 오류 )

 

    void Test()
    {
    }

 

    void Test()    // error C2084: function 'void __cdecl Test(void)' already has a body
    {
    }

 

    void main()
    {
        Test();
    }

 

 

3. LNK2005 오류코드

 

    다양한 기능을 가진 프로그램을 하다보면 하나의 소스파일로 작업하지 않고 의미있는 코드를 그룹지어 여러개의

    소스로 나누어 작업하는 경우도 많습니다. 예를들의 자신의 프로젝트가 Exam1.cpp 의 소스파일로만 구성될수도

    있지만 Exam1.cpp, Exam2.cpp 와 같이 두개의 소스 파일로 구성될수도 있습니다.

    

    프로젝트를 구성하고 있는 소스파일은 관리를 편하게 하기 위해서 나누어진것일뿐 실제로는 하나의 소스라고

    생각하시면 됩니다. 따라서 자신의 프로젝트가  Exam1.cpp, Exam2.cpp 이라는 두개의 소스 파일로 구성되어

    있고 아래와 같이 소스를 작성해보겠습니다.

 

    // Exam1.cpp

    int g_data;

    

    void main()

    {

    }

 

    // Exam2.cpp

    int g_data;

   

    void Test()

    {

    }

   

    위 예제를 컴파일해보면 각각의 소스파일에는 문제가 없기 때문에 정상적으로 컴파일되어 Exam1.obj, Exam2.obj 로

    목적파일이 만들어집니다. 하지만 두개의 목적파일을 링크하여 실행파일 만드는 과정에서 아래와 같은 오류가  

    발생합니다. 이것은 각각 소스에서 사용한 g_data 라는 전역변수가 전체 프로그램(프로젝트)에서 봤을때는 중복해서

    선언된 것이기 때문에 오류처리된 것입니다. 즉, 전역변수는 단위소스에서만 전역적으로 사용 가능한것이 아니라

    프로그램(프로젝트) 전체에서 전역적으로 사용한것이기 때문입니다.

 

    int g_data" (?g_data@@3HA) already defined in Exam1.obj

 

    이렇게 발생한 오류를 해결하는 방법은 크게 두가지 입니다.

   

   

    3.1 두개의 전역변수가 이름은 같지만 서로 다른 의미로 사용된 경우

   

        가장 간단한 방법은 둘중에 한개의 전역변수의 이름을 변경하는 것입니다. 하지만, 여러가지 이유로 이름을 변경할 수

        없는 상황이라면 아래와 같이 전역변수 앞에 static 키워드를 붙여서 사용하면 오류를 제거할수 있습니다.

        ( 중복된 두개의 전역변수중에 한군데만 static 을 사용해도 오류가 제거됩니다. )

   

        static int g_data;

 

        전역변수 앞에 static 키워드를 사용하면 해당 소스파일에서만 전역적으로 사용할수 있는 전역변수로 범위가 한정됩니다.

 

    

    3.2 두개의 전역변수가 같은 의미로 사용된 경우 ( 동일한 변수 이여야 하는 경우 )

 

        하나의 전역변수를 두개의 소스파일에서 사용하고 싶은 경우라면 한쪽을 원본으로 하고 나머지 한쪽은 참조하는 형식으로

        선언해서 사용해야 합니다. 위와 같은 경우라면 Exam1.cpp 에 선언된 g_data 전역 변수는 그대로 유지하고 Exam2.cpp 에

        선언된 g_data 전역변수 앞에 extern 키워드를 추가해서 사용하면 됩니다. 소스를 재구성해보면 아래와 같습니다.

   

        // Exam1.cpp

        int g_data;

  

        void main()

        {

         }

 

        // Exam2.cpp

        extern int g_data;

  

        void Test()

        {

         }

  

        extern 을 전역변수 선언에 같이 사용하면 전체 프로그램(프로젝트)내에 동일한 이름을 가진 전역변수가 존재하고

        그 전역변수를 이 소스파일에서 참조해서 사용하겠다는 뜻이됩니다.

   

   

    LNK2005 오류는 전역변수에서만 발생하는것이 아니라 함수도 같은 이름을 사용하면 발생합니다. ( 오버로딩이 적용 안되는 경우 )

    아래와 같이 Exam1.cpp 와 Exam2.cpp 가 하나의 프로젝트에 포함되어 있다면 각각의 소스파일은 정상적으로 컴파일 되겠지만

    링크시에

 

    void __cdecl Test(void)" (?Test@@YAXXZ) already defined in Exam1.obj

 

    이라는 오류가 발생합니다. 이것도 하나의 프로그램(프로젝트)에 동일한 이름을 가진 두개의 함수가 정의 되었기 때문에

    발생한 오류입니다.

 

    // Exam1.cpp

    void Test()

    {

    }

    

    void main()

    {

        Test();

    }

   

    // Exam2.cpp

    void Test()

    {

    }

 

    void MyFunc()

    {

         Test();

    }

 

    이 문제를 해결하려면 전역변수와 마찬가지로 두가지 해결 방법이 있습니다.

 

  

    3.3 두개의 함수가 이름은 같지만 서로 다른 의미로 사용된 경우

 

        전역변수와 마찬가지로 두개의 함수의 이름을 다르게 하거나 해당 함수앞에 static 키워드를 사용하여 사용범위를 제한하면

        오류를 해결할수 있습니다. 이때도 둘중에 한곳에만 static 을 사용하면 됩니다.

   

        // Exam1.cpp

        void Test()

        {

        }

 

        void main()

        {

            Test();

        }

  

        // Exam2.cpp

        static void Test()

        {

        }

  

        void MyFunc()

        {

            Test();   // Exam2.cpp 에 있는 Test 함수가 호출됨

        }

 

 

    3.4 두개의 함수가 동일하게 사용되어야 하는 경우 ( 양쪽 소스에서 같은 Test 함수를 호출하고 싶은 경우 )

   

        같은 프로젝트에 포함된 다른 소스에 존재하는 함수를 사용하고 싶다면 해당 함수의 원형(prototype)만 선언해주고

       사용하면 됩니다.

 

        // Exam1.cpp

        void Test()

        {

        }

 

        void main()

        {

            Test();

        }

 

        // Exam2.cpp

        void Test();    // 사용하고 싶은 함수의 원형을 명시한다.

 

        void MyFunc()

        {

            Test(); // Exam1.cpp 에 있는 Test 함수가 호출됨

        }

 

 

사실 위와 같은 경우는 소스를 수정하여 오류를 제거할수 있기 때문에 이런 오류 코드가 문제가 되지 않습니다. 정말 난감한 문제는

자신이 두개의 라이브러리(Library, *.lib)를 사용해야 하는데 각 라이브러리에 동일한 이름을 가진 함수가 있을때도 LNK2005 오류가

발생한다는 것입니다. 자신이 만든 라이브러리라면 소스를 수정해서 다시 라이브러리를 만들면 되겠지만 소스가 없는 없다면

Visual C++ 의 링크 옵션을 조절해서 해결을 해야합니다.

  

이런 경우는 상황에 따라서 대처하는 방법이 다르기 때문에 해결책을 직접적으로 알려드리기는 어려울듯합니다. 그래서

관련해서 예시가 있으니 아래에 링크해드린 자료를 한번 읽어보시기 바랍니다.

  

http://support.microsoft.com/kb/148652/ko

   

 

저는 www.tipssoft.com 사이트의 관리자이며 위 자료는 해당 사이트에도 동일하게 게시되어 있음을 알려드립니다.
www.tipssoft.com 사이트는 프로그래머들의 정보공유를 위해 제가 운영하고 있는 사이트 입니다.
  
이 게시물과 동일한 자료의 www. tipssoft.com 게시물 URI 는 다음과 같습니다.
http://www.tipssoft.com/bulletin/tb.php/FAQ/1156 )

반응형
반응형

http://process3.blog.me/20065867268


최근에 덤프를 하나 분석하고 있는데 동기화 관련해서 이슈가 발생한것 같습니다. criticalsection 관련 WinDbg 명령하나를 정리합니다. 필요하신 분들 참고하세요~

 

1) 문제가 있는 CriticalSection 오브젝트가 있는지 확인한다.

 

0:019> !locks -o
Looking for orphaned critical sections

CritSec at 100a4824 could not be read
Perhaps the critical section was a global variable in a dll that was unloaded?

CritSec at 100a4648 could not be read
Perhaps the critical section was a global variable in a dll that was unloaded?

CritSec at 100a47e0 could not be read
Perhaps the critical section was a global variable in a dll that was unloaded?

CritSec at 100a4660 could not be read
Perhaps the critical section was a global variable in a dll that was unloaded?

Scanned 650 critical sections

 

총 650개 critical sections 중에 약 4개가 문제가 있는것 같습니다.

 

2)!cs 명령을 통해서 좀 더 자세하게 확인해 보겠습니다.

0:019> !cs -l
-----------------------------------------
DebugInfo          = 0x00154990
Critical section   = 0x008f211c (+0x8F211C)
LOCKED
LockCount          = 0x0
OwningThread       = 0x000001c0
RecursionCount     = 0x1
LockSemaphore      = 0x0
SpinCount          = 0x00000000
-----------------------------------------
DebugInfo          = 0x001497a0
Critical section   = 0x008f335c (+0x8F335C)
LOCKED
LockCount          = 0x0
OwningThread       = 0x00000204
RecursionCount     = 0x1
LockSemaphore      = 0x0
SpinCount          = 0x00000000
-----------------------------------------
DebugInfo          = 0x00149840
Critical section   = 0x008f304c (+0x8F304C)
LOCKED
LockCount          = 0x0
OwningThread       = 0x00000208
RecursionCount     = 0x1
LockSemaphore      = 0x0
SpinCount          = 0x00000000
Cannot read structure field value at 0x100a4828, error 0
Cannot determine if the critical section is locked or not.
-----------------------------------------
Critical section   = 0x100a4824 (+0x100A4824)
DebugInfo          = 0x0015a198
Cannot read structure field value at 0x100a464c, error 0
Cannot determine if the critical section is locked or not.
-----------------------------------------
Critical section   = 0x100a4648 (+0x100A4648)
DebugInfo          = 0x0015a2d0
Cannot read structure field value at 0x100a47e4, error 0
Cannot determine if the critical section is locked or not.
-----------------------------------------
Critical section   = 0x100a47e0 (+0x100A47E0)
DebugInfo          = 0x0015a2f8
Cannot read structure field value at 0x100a4664, error 0
Cannot determine if the critical section is locked or not.
-----------------------------------------
Critical section   = 0x100a4660 (+0x100A4660)
DebugInfo          = 0x0015a320
-----------------------------------------
DebugInfo          = 0x001676d8
Critical section   = 0x009609ac (+0x9609AC)
LOCKED
LockCount          = 0x0
OwningThread       = 0x0000064c
RecursionCount     = 0x1
LockSemaphore      = 0x0
SpinCount          = 0x00000000
-----------------------------------------
DebugInfo          = 0x001771e8
Critical section   = 0x00978664 (+0x978664)
LOCKED
LockCount          = 0x0
OwningThread       = 0x000001c0
RecursionCount     = 0x1
LockSemaphore      = 0x0
SpinCount          = 0x00000000
-----------------------------------------
DebugInfo          = 0x001478b0
Critical section   = 0x00978684 (+0x978684)
LOCKED
LockCount          = 0x0
OwningThread       = 0x000001c0
RecursionCount     = 0x1
LockSemaphore      = 0x0
SpinCount          = 0x00000000

...

 

이 프로그램이 생각보다 많은 Critical Section 오브젝트를 사용하고 LOCKED 되어 있는것도 많습니다.

또한 Looking for orphaned critical sections(소유자가 없는 Critical Section 오브젝트)도 4개나 있습니다.

 

3) 소유주가 없는 Critical Section 오브젝트를 좀 더 조사해 봅시다.

0:019> !cs -o 0x100a4648 
Cannot read DebugInfo adddress at 0x100a4648. Possible causes:
 - The critical section is not initialized, deleted or corrupted
 - The critical section was a global variable in a DLL that was unloaded
 - The memory is paged out

Cannot read structure field value at 0x100a464c, error 0
Cannot determine if the critical section is locked or not.
-----------------------------------------
Critical section   = 0x100a4648 (+0x100A4648)
DebugInfo          = 0x00000137

 아래 3가지 경우중에 하나이면 소유주가 없는  Critical Section 오브젝트가 생겨서 크래쉬가 발생하고 문제 해결이 정말 어려워지는 버그가 발생합니다.

 - 초기화 되지 않았거나 지워졌거나 오염된 경우(The critical section is not initialized, deleted or corrupted)
 - DLL에서 전역변수로 Critical Section 오브젝트가 선언되었는데 DLL이 언로드된 경우 (The critical section was a global variable in a DLL that was unloaded)
 - 메모리가 페이지 아웃된 경우 (The memory is paged out)

 

 

[Critical section 에서 문제가 발생할 수 있는 상황 정리]

1. InitializeCriticalSection(...) 함수를 호출 하지 않았다.
2. 여러번 InitializeCriticalSection(...) 호출되었고 DeleteCriticalSection(...)이 한번도 호출되지 않은 상황에서 다시 초기화된 경우
3. DeleteCriticalSection(...) 호출되었다 그러나 Critical section  오브젝트가 계속해서 참조되고 사용된다.
4. 스레드에서 EnterCriticalSection(...) 호출되고 사용된다. 그러나 LeaveCriticalSection(...).함수를 호출하지 않았다. 그리고 다른 스레드에서 EnterCriticalSection(...).함수를 호출해서 사용한다.

즉, 메모리에 선언되지 않았거나 메모리에서 지워진  Critical section   오브젝트를 사용하면 큰일 난다

 

1)초기화 하지 않은 Critical section 오브젝트

// Not initilize the Critical section.
// Global variable
CRITICAL_SECTION CriticalSection; 
int _tmain(int argc, _TCHAR* argv[])
{
    //InitializeCriticalSection(&CriticalSection);
    EnterCriticalSection(&CriticalSection);
  
    LeaveCriticalSection(&CriticalSection);

    DeleteCriticalSection(&CriticalSection);
    return 0;
}

 

2)삭제된 Critical section 오브젝트 참조하기
// Global variable
CRITICAL_SECTION CriticalSection; 
DWORD WINAPI ThreadProc( LPVOID lpParameter )
{
 //InitializeCriticalSection(&CriticalSection);
    // Request ownership of the critical section.
    EnterCriticalSection(&CriticalSection); 
    // Release ownership of the critical section.
    LeaveCriticalSection(&CriticalSection);
 DeleteCriticalSection(&CriticalSection);
 return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
    // Initialize the critical section one time only.
    InitializeCriticalSection(&CriticalSection);
 CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
  
 Sleep(3000);
 EnterCriticalSection(&CriticalSection);
 LeaveCriticalSection(&CriticalSection);
 DeleteCriticalSection(&CriticalSection);
 return 0;
}


출처 : 다년간의 프로그램밍 삽질(경험)->요즈음 나를 괴롭히는 버그... ㅠㅠ 그리고 구글 검색으로부터...

반응형
반응형

병렬 스택 창 사용

Visual Studio 2010
이 항목은 아직 평가되지 않았습니다.이 항목 평가

병렬 스택 창은 다중 스레드 응용 프로그램을 디버깅할 때 유용합니다. 스레드 뷰에는 응용 프로그램의 모든 스레드에 대한 호출 스택 정보가 표시됩니다. 따라서 스레드와 스레드 스택 프레임 간을 탐색할 수 있습니다. 관리되는 코드에서 작업 뷰System.Threading.Tasks::Task 개체의 호출 스택이 표시됩니다. 네이티브 코드에서 작업 뷰는 작업 그룹병렬 알고리즘비동기 에이전트 및 간단한 작업의 호출 스택이 표시됩니다.

다음 그림에서는 Main에서 A, B 및 외부 코드로 차례로 이동한 하나의 스레드를 보여 줍니다.다른 두 스레드는 외부 코드에서 시작한 후 A로 이동했지만, 그 중 하나는 B로 진행한 후 외부 코드로 진행했고 다른 하나는 C로 진행한 후 AnonymousMethod로 진행했습니다.



그림에서 현재 스레드의 호출 경로는 파란색으로 강조 표시되며, 활성 스택 프레임은 노란색 화살표로 표시됩니다. 병렬 스택 창에서 다른 메서드를 선택하여 현재 스택 프레임을 변경할 수 있습니다.이렇게 하면 선택한 메서드가 현재 스레드의 일부인지 아니면 다른 스레드의 일부인지에 따라 현재 스레드가 전환될 수 있습니다.다음 표에서는 그림에 표시된 병렬 스택 창의 기본 기능에 대해 설명합니다.

설명선 문자

요소 이름

설명

A

호출 스택 세그먼트 또는 노드

하나 이상의 스레드에 대한 일련의 메서드 컨텍스트를 포함합니다.노드에 연결된 화살표 선이 없으면 스레드에 대한 전체 호출 경로를 나타냅니다.

B

파란색 강조 표시

현재 스레드의 호출 경로를 나타냅니다.

C

화살표 선

노드를 연결하여 스레드에 대한 전체 호출 경로를 구성합니다.

D

노드 머리글에 대한 도구 설명

호출 경로가 이 노드를 공유하는 각 스레드의 ID 및 사용자 정의 이름을 표시합니다.

E

메서드 컨텍스트

동일한 메서드에 있는 하나 이상의 스택 프레임을 나타냅니다.

F

메서드 컨텍스트에 대한 도구 설명

메서드 컨텍스트가 나타내는 모든 스택 프레임의 세부 정보를 표시합니다.현재 스레드의 스택 프레임이 굵게 표시됩니다.

또한 그래프가 너무 커서 창에 맞지 않는 경우에는 병렬 스택 창의 주 창에 Bird's Eye View 아이콘이 표시됩니다.전체 그래프를 창에서 보려면 이 아이콘을 클릭하면 됩니다.

다음 표에서는 활성 및 현재 스택 프레임에 대한 정보를 제공하는 아이콘을 설명합니다.

아이콘

설명

병렬 스택 노란색 화살표

메서드 컨텍스트에 현재 스레드의 활성 스택 프레임이 포함되어 있음을 나타냅니다.

병렬 스택 스레드 아이콘

메서드 컨텍스트에 현재 스레드가 아닌 스레드의 활성 스택 프레임이 포함되어 있음을 나타냅니다.

병렬 스택 녹색 화살표

메서드 컨텍스트에 현재 스택 프레임이 포함되어 있음을 나타냅니다.메서드 이름이 나타나는 모든 노드에서 메서드 이름이 굵게 표시됩니다.

다음 그림과 표에서는 병렬 스택 도구 모음에서 사용할 수 있는 컨트롤에 대해 설명합니다.

병렬 스택 창 도구 모음

설명선 문자

컨트롤

설명

A

스레드/작업 콤보 상자

스레드의 호출 스택과 작업의 호출 스택 간에 뷰를 전환합니다.자세한 내용은 작업 뷰와 스레드 뷰를 참조하십시오.

B

플래그 설정된 항목만 표시

스레드 창이나 병렬 작업 창에서 플래그 설정된 스레드 또는 작업에 대해서만 호출 스택을 표시합니다.

C

메서드 뷰 설정/해제

스택 뷰와 메서드 뷰 간을 전환합니다.자세한 내용은 메서드 뷰를 참조하십시오.

D

현재 스택 프레임으로 자동 스크롤

현재 스택 프레임이 뷰에 표시되도록 다이어그램을 자동 스크롤합니다.이 기능은 다른 창에서 현재 스택 프레임을 변경하거나 큰 다이어그램에서 새 중단점을 적중할 때 유용합니다.

E

확대/축소 컨트롤 설정/해제

확대/축소 컨트롤을 표시하거나 숨깁니다.확대/축소 컨트롤의 표시 여부와 관계없이 Ctrl 키를 누른 상태에서 마우스 휠을 돌려서 확대/축소할 수도 있습니다.

상황에 맞는 메뉴 항목

다음 그림과 표에서는 스레드 뷰와 작업 뷰에서 메서드 컨텍스트를 마우스 오른쪽 단추로 클릭할 때 사용할 수 있는 바로 가기 메뉴 항목에 대해 설명합니다.마지막 6개 항목은 호출 스택 창에서 직접 가져온 것으로 새로운 동작을 제공하지 않습니다.

병렬 스택 상황에 맞는 메뉴

Menu Item

설명

작업으로 이동 또는 스레드로 이동

도구 모음의 콤보 상자와 같은 기능을 수행하지만 동일한 스택 프레임이 강조 표시된 상태로 유지됩니다.

프레임으로 전환

호출 스택 창의 해당 메뉴 명령과 동일합니다.그러나 병렬 스택을 사용하는 경우 여러 프레임이 하나의 메서드 컨텍스트에 해당할 수 있습니다.따라서 메뉴 항목에 하위 메뉴가 있고 각각의 하위 메뉴가 특정 스택 프레임을 나타냅니다.스택 프레임 중 하나가 현재 스레드에 있으면 스택 프레임에 해당하는 메뉴가 선택됩니다.

소스 코드로 이동

사용자가 마우스 오른쪽 단추로 클릭한 스택 프레임에 해당하는 소스 코드의 위치로 이동합니다.

디스어셈블리로 이동

사용자가 마우스 오른쪽 단추로 클릭한 스택 프레임에 해당하는 디스어셈블리 창의 위치로 이동합니다.

외부 코드 표시

외부 코드를 표시하거나 숨깁니다.

16진수 표시

10진수 표시와 16진수 표시 간을 전환합니다.

기호 로드 정보

해당하는 대화 상자를 표시합니다.

기호 설정

해당하는 대화 상자를 표시합니다.

응용 프로그램에서 System.Threading.Tasks::Task 개체(관리 코드)나 task_handle 개체(네이티브 코드)를 사용하여 병렬화를 표현하는 경우 병렬 스택 창 도구 모음의 콤보 상자를 사용하여 작업 뷰로 전환할 수 있습니다.작업 뷰에는 스레드 대신 작업의 호출 스택이 표시됩니다.작업 뷰는 다음과 같이 스레드 뷰와 다릅니다.

  • 작업을 실행하고 있지 않은 스레드의 호출 스택이 표시되지 않습니다.

  • 작업을 실행 중인 스레드의 호출 스택은 맨 위와 맨 아래에서 시각적으로 잘려 작업과 가장 많이 관련된 프레임을 표시합니다.

  • 여러 작업이 한 스레드에 있으면 이러한 작업의 호출 스택이 개별 노드로 분할됩니다.

다음 그림의 오른쪽에는 병렬 스택 작업 뷰가 표시되고 왼쪽에는 해당 스레드 뷰가 표시됩니다.

병렬 스택 작업 뷰

전체 호출 스택을 보려면 스택 프레임을 마우스 오른쪽 단추로 클릭하고 스레드로 이동을 클릭하여 스레드 뷰로 전환하면 됩니다.

그림에서 작업 뷰의 노드 머리글은 노드가 표현하는 작업의 상태를 나타냅니다.앞의 표에서 설명했듯이 노드 머리글 또는 메서드 컨텍스트를 가리키면 추가 정보를 볼 수 있습니다.다음 이미지에서는 스레드 뷰와 작업 뷰에 대한 정보를 도구 설명으로 보여 줍니다.

병렬 스택 도구 설명

스레드 뷰나 작업 뷰에서 도구 모음의 메서드 뷰 아이콘을 클릭하여 현재 메서드를 축으로 그래프를 회전할 수 있습니다.메서드 뷰에서는 현재 메서드를 호출하거나 현재 메서드에 의해 호출되는 모든 스레드에 대한 메서드를 모두 한눈에 볼 수 있습니다.다음 그림에서는 스레드 뷰를 보여 주며, 메서드 뷰에서 동일한 정보가 어떻게 표시되는지도 보여 줍니다.

병렬 스택 메서드 뷰

새 스택 프레임으로 전환하여 해당 메서드를 현재 메서드로 설정하고 창에 새 메서드에 대한 모든 호출자 및 호출 수신자를 표시합니다.이렇게 하면 메서드가 호출 스택에 표시되는지 여부에 따라 일부 스레드가 뷰에 나타나거나 사라집니다.스택 뷰로 돌아가려면 메서드 뷰 도구 모음 단추를 다시 클릭합니다.


http://msdn.microsoft.com/ko-kr/library/dd998398(v=vs.100).aspx



BLOG main image


약간 과장을 보태서 전체 스레드를 보는데 있어서만큼은 이 기능이 이렇게 편해도 되나싶을 정도의 기능인듯하다
windbg로 보기엔 귀찮은 일을 한눈에 알 수 있게 해준다


반응형
반응형

BLOG main image


http://3dmpengines.tistory.com/1182 의 글을 먼저 본 후 읽어나가면 되고

스레드창을 활용한 글이라고 보면 된다




연습: 다중 스레드 응용 프로그램 디버깅

Visual Studio 2010
이 항목은 아직 평가되지 않았습니다.이 항목 평가

이 항목은 다음 언어에 적용됩니다.

Visual Studio Edition

Visual Basic

C#

F#

C++

Web Developer

Express

항목이 적용되지 않음항목이 적용되지 않음항목이 적용되지 않음항목이 적용됨항목이 적용되지 않음

Pro, Premium 및 Ultimate

항목이 적용됨항목이 적용됨항목이 적용되지 않음항목이 적용됨항목이 적용됨

Visual Studio 2010은 다중 스레드 응용 프로그램을 쉽게 디버깅할 수 있도록 향상된 스레드 창과 그 밖의 향상된 사용자 인터페이스를 제공합니다. 이 연습은 몇 분 정도 소요되지만 연습을 완료하면 다중 스레드 응용 프로그램 디버깅을 위한 새로운 인터페이스 기능에 익숙해질 수 있습니다.

이 연습을 시작하려면 다중 스레드 응용 프로그램 프로젝트가 필요합니다. 여기에 나열된 단계에 따라 프로젝트를 만드십시오.

연습 프로젝트를 만들려면

  1. 파일 메뉴에서 새로 만들기를 선택한 다음 프로젝트를 클릭합니다.

    새 프로젝트 대화 상자가 나타납니다.

  2. 프로젝트 형식 상자에서 Visual BasicVisual C#Visual C++ 등 선택할 언어를 클릭합니다.

  3. 템플릿 상자에서 콘솔 응용 프로그램 또는 CLR 콘솔 응용 프로그램을 선택합니다.

  4. 이름 상자에 MyThreadWalkthroughApp라는 이름을 입력합니다.

  5. 확인을 클릭합니다.

    새 콘솔 프로젝트가 나타납니다. 프로젝트가 만들어지면 소스 파일이 나타납니다. 선택한 언어에 따라 소스 파일 이름이 Module1.vb, Program.cs 또는 MyThreadWalkthroughApp.cpp일 수 있습니다.

  6. 소스 파일에 나타나는 코드를 삭제하고 스레드 만들기 및 시작할 때 데이터 전달 항목의 "스레드 만들기" 단원에 나타나는 예제 코드로 바꿉니다.

  7. 파일 메뉴에서 모두 저장을 클릭합니다.

연습을 시작하려면

  • 소스 창에서 다음 코드를 찾습니다.

    Thread.Sleep(3000) 
    Console.WriteLine(
    
Thread::Sleep(3000);
Console.WriteLine();

디버깅을 시작하려면

  1. Console.WriteLine 문을 마우스 오른쪽 단추로 클릭하고 중단점을 가리킨 다음 중단점 삽입을 클릭합니다.

    소스 창 왼쪽의 여백에 빨간 공이 나타납니다. 이 공은 이 위치에 중단점이 설정되었음을 나타냅니다.

  2. 디버그 메뉴에서 디버깅 시작을 클릭합니다.

    디버깅을 시작하면 콘솔 응용 프로그램이 실행되다가 중단점에서 중지됩니다.

  3. 이때 콘솔 응용 프로그램 창에 포커스가 있으면 Visual Studio 창을 클릭하여 Visual Studio로 포커스를 되돌립니다.

  4. 소스 창에서 다음 코드가 있는 줄을 찾습니다.

    Thread.Sleep(5000) 
    
Thread::Sleep(3000);

스레드 마커를 찾으려면

  1. 스레드 창을 마우스 오른쪽 단추로 클릭한 다음 소스의 스레드 표시를 클릭합니다.

  2. 창 왼쪽의 여백을 확인합니다. 이 줄에는 실 모양 아이콘 두 개가 있습니다. 하나는 빨간색이고 다른 하나는 파란색입니다. 스레드 마커는 이 위치에서 스레드가 중지되었음을 나타냅니다. 스레드가 이 위치에서 중지되었을 수 있습니다.

  3. 스레드 마커에 포인터를 올려 놓습니다. DataTip이 나타납니다. DataTip을 통해 중지된 각 스레드의 이름과 스레드 ID 번호를 알 수 있습니다. 이 경우 이름이 <noname>인 스레드 한 개만 있습니다.

  4. 스레드 마커를 마우스 오른쪽 단추로 클릭합니다. 바로 가기 메뉴에서 선택 내용을 확인합니다.

이 아이콘이 스레드 마커입니다.

스레드 마커

Visual Studio 2008에서는 특히 주의할 스레드에 플래그를 지정할 수 있습니다.스레드에 플래그를 지정하면 중요한 스레드를 추적하고 중요하지 않은 스레드는 무시할 수 있습니다.

스레드에 플래그를 지정하려면

  1. 보기 메뉴에서 도구 모음을 가리킵니다.

    디버그 위치 도구 모음이 선택되어 있는지 확인합니다.

  2. 디버그 위치 도구 모음으로 이동하여 스레드 목록을 클릭합니다.

    참고참고

    프로세스스레드 및 스택 프레임이라는 세 개의 중요한 목록을 통해 이 도구 모음을 인식할 수 있습니다.

  3. 목록에 나타나는 스레드 수를 확인합니다.

  4. 소스 창으로 돌아가 스레드 마커를 다시 마우스 오른쪽 단추로 클릭합니다.

  5. 바로 가기 메뉴에서 플래그를 가리킨 다음 스레드 이름과 ID 번호를 클릭합니다.

  6. 디버그 위치 도구 모음으로 돌아가 스레드 목록을 다시 클릭합니다.

    플래그가 지정된 스레드만 목록에 나타납니다. 스레드 목록 바로 오른쪽에 플래그 단추가 있습니다.이전에는 희미하게 표시되던 단추의 플래그 아이콘이지금은 밝은 빨강으로 표시됩니다.

  7. 플래그 아이콘에 포인터를 올려 놓습니다.

    팝업이 나타납니다.이 팝업을 통해 스레드 목록의 모드가 플래그가 지정된 스레드만 표시임을 알 수 있습니다.

  8. 플래그 단추를 클릭하여 모든 스레드 표시 모드로 전환합니다.

  9. 스레드 목록을 다시 클릭하고 다시 모든 스레드가 표시되는지 확인합니다.

  10. 플래그 단추를 클릭하여 플래그가 지정된 스레드만 표시로 전환합니다.

  11. 디버그 메뉴에서 을 가리킨 다음 스레드를 클릭합니다.

    스레드 창이 나타납니다.스레드 한 개에 중요한 플래그 아이콘이 연결되어 있습니다.

  12. 소스 창에서 스레드 마커를 다시 마우스 오른쪽 단추로 클릭합니다.

    바로 가기 메뉴에서 선택할 수 있는 항목을 확인합니다. 플래그 대신 플래그 해제가 표시됩니다. 플래그 해제를 클릭하지 마십시오.

  13. 스레드의 플래그를 해제하기 위한 다음 절차로 이동합니다.

스레드의 플래그를 해제하려면

  1. 스레드 창에서 플래그가 지정된 스레드에 해당하는 줄을 마우스 오른쪽 단추로 클릭합니다.

    바로 가기 메뉴가 표시됩니다.이 메뉴에 플래그 해제 및 모든 스레드 플래그 해제 옵션이 있습니다.

  2. 스레드의 플래그를 해제하려면 플래그 해제를 클릭합니다.

  3. 빨간색 플래그 아이콘을 클릭합니다.

  4. 디버그 위치 도구 모음을 다시 확인합니다.플래그 단추가 다시 희미해집니다.플래그가 지정된 스레드의 플래그만 해제됩니다.플래그가 지정된 스레드가 없으므로 도구 모음은 다시 모든 스레드 표시 모드로 돌아갑니다. 스레드 목록을 클릭하고 모든 스레드가 표시되는지 확인합니다.

  5. 스레드 창으로 돌아가 정보 열을 검사합니다.

    각 열 맨 위의 단추에는 대부분 열을 식별하는 제목이 있습니다.그러나 왼쪽 첫째 열에는 제목이 없습니다.대신 플래그 윤곽선에 해당하는 아이콘이 있습니다.스레드 목록의 각 행에도 같은 윤곽선이 있습니다.이 윤곽선은 스레드의 플래그가 해제되었음을 나타냅니다.

  6. 목록 아래쪽에서 둘째 스레드와 셋째 스레드의 플래그 윤곽선을 클릭합니다.

    플래그 아이콘은 빈 윤곽선 대신 빨간색으로 변합니다.

  7. 플래그 열 맨 위의 단추를 클릭합니다.

    단추를 클릭하면 스레드 목록의 순서가 변경됩니다.스레드 목록은 플래그가 지정된 스레드가 맨 위에 오도록 정렬됩니다.

  8. 플래그 열 맨 위의 단추를 다시 클릭합니다.

    정렬 순서가 다시 변경됩니다.

스레드 창에 대해 자세히 알아 보려면

  1. 스레드 창에서 왼쪽 셋째 열을 확인합니다.이 열의 맨 위에 있는 단추에 ID라고 표시되어 있습니다.

  2. ID를 클릭합니다.

    스레드 목록이 스레드 ID 번호순으로 정렬됩니다.

  3. 목록의 스레드를 마우스 오른쪽 단추로 클릭합니다.바로 가기 메뉴에서 16진수 표시를 클릭합니다.

    스레드 ID 번호 형식이 변경됩니다.

  4. 목록의 스레드에 마우스 포인터를 올려 놓습니다.

    잠시 후 DataTip이 나타납니다.여기에 스레드의 부분 호출 스택이 표시됩니다.

  5. 범주 레이블이 있는 왼쪽에서 넷째 열을 확인합니다.스레드가 범주로 분류되어 있습니다.

    프로세스에서 만든 첫째 스레드를 주 스레드라고 합니다.스레드 목록에서 주 스레드를 찾습니다.

  6. 주 스레드를 마우스 오른쪽 단추로 클릭하고 스레드로 전환을 클릭합니다.

    경고 대화 상자가 나타납니다.이 대화 상자에서 Visual Studio가 주 스레드의 소스 코드를 표시할 수 없음을 알 수 있습니다.

    확인을 클릭합니다.

  7. 호출 스택 창과 디버그 위치 도구 모음을 확인합니다.

    호출 스택 창의 내용이 변경되었습니다.

스레드를 전환하려면

  1. 스레드 창에서 왼쪽 둘째 열을 확인합니다.이 열의 맨 위에 있는 단추에는 텍스트나 아이콘이 없습니다.이 열은 활성 스레드열입니다.

  2. 활성 스레드 열의 스레드 하나에 노랑 화살표가 있습니다.이 화살표는 활성 스레드 표시기입니다.

  3. 활성 스레드 표시기가 있는 스레드 ID 번호를 메모합니다.활성 스레드 표시기를 다른 스레드로 이동하겠지만 작업이 끝나면 다시 돌려 놓아야 합니다.

  4. 다른 스레드를 마우스 오른쪽 단추로 클릭하고 스레드로 전환을 클릭합니다.

  5. 소스 창에서 호출 스택 창을 확인합니다.내용이 변경되었습니다.

  6. 디버그 위치 도구 모음을 확인합니다.여기서도 활성 스레드가 변경되었습니다.

  7. 디버그 위치 도구 모음으로 이동합니다. 스레드 상자를 클릭하고 드롭다운 목록에서 다른 스레드를 선택합니다.

  8. 스레드 창을 확인합니다.활성 스레드 표시기가 변경되었습니다.

  9. 소스 창에서 스레드 마커를 마우스 오른쪽 단추로 클릭합니다.바로 가기 메뉴에서 전환을 가리킨 다음 스레드 이름과 ID 번호를 클릭합니다.

    스레드 창, 디버그 위치 도구 모음의 스레드 상자, 소스 창의 스레드 표시기를 사용하여 활성 스레드를 변경하는 방법을 살펴 보았습니다.

    스레드 표시기를 사용하면 특정 위치에서 중지된 스레드로만 전환할 수 있습니다. 스레드 창 및 디버그 위치 도구 모음을 사용하면 임의의 스레드로 전환할 수 있습니다.

스레드를 중지 및 해제하려면

  1. 스레드 창에서 스레드를 마우스 오른쪽 단추로 클릭한 다음 중지를 클릭합니다.

  2. 활성 스레드 열을 확인합니다.세로 막대 쌍이 나타납니다.이 두 개의 파란색 막대는 스레드가 중지되었음을 나타냅니다.

  3. 일시 중단 열을 확인합니다.스레드의 일시 중단 횟수가 1입니다.

  4. 중지된 스레드를 마우스 오른쪽 단추로 클릭한 다음 재개를 클릭합니다.

    활성 스레드 열과 일시 중단 열이 변경됩니다.


반응형
반응형

BLOG main image


스레드창의 기능을 좀 더 자세하게 알 수 있는 글이지만 대강만 읽어도 사용법을 금방 알 수 있다




출처 : http://msdn.microsoft.com/ko-kr/library/w15yf86f(v=vs.100).aspx


방법: 스레드 창 사용

Visual Studio 2010
이 항목은 아직 평가되지 않았습니다.이 항목 평가

이 항목은 다음 언어에 적용됩니다.

Edition

Visual Basic

C#

F#

C++

Web Developer

Express

항목이 적용되지 않음항목이 적용되지 않음항목이 적용되지 않음항목이 적용되지 않음항목이 적용되지 않음

Pro, Premium 및 Ultimate

항목이 적용됨항목이 적용됨항목이 적용됨항목이 적용됨항목이 적용됨

스레드 창에서 디버깅 중인 응용 프로그램의 스레드를 검사하고 작업할 수 있습니다.

스레드 창에는 각 행이 응용 프로그램의 스레드를 나타내는 테이블이 있습니다. 기본적으로 이 테이블에는 응용 프로그램의 모든 스레드가 나열되지만 목록을 필터링하여 관심 있는 스레드만 표시할 수 있습니다. 열마다 다른 유형의 정보가 있습니다. 일부 열을 숨길 수도 있습니다. 모든 열을 표시하면 왼쪽부터 다음 정보가 나타납니다.

  • 플래그 열 - 주의해야 할 스레드에 표시할 수 있습니다. 스레드에 플래그를 설정하는 방법에 대한 자세한 내용은 방법: 스레드에 플래그 지정 및 스레드의 플래그 해제를 참조하십시오.

  • 활성 스레드 열 - 노란색 화살표는 활성 스레드를 나타냅니다. 화살표의 윤곽선은 실행이 중단되고 디버거가 실행된 스레드를 나타냅니다.

  • ID 열 - 각 스레드의 식별 번호가 표시됩니다.

  • 관리 ID 열 - 관리되는 스레드의 관리 식별 번호가 표시됩니다.

  • 범주 열 - 사용자 인터페이스 스레드, 원격 프로시저 호출 처리기 또는 작업자 스레드로 스레드가 분류됩니다. 특정 범주는 응용 프로그램의 주 스레드를 식별합니다.

  • 이름 열 - 각 스레드가 이름(있는 경우) 또는 <이름 없음>으로 식별됩니다.

  • 위치 열 - 스레드가 실행 중인 위치가 표시됩니다. 이 위치를 확장하여 스레드의 전체 호출 스택을 표시할 수 있습니다.

  • 우선 순위 열 - 시스템에서 각 스레드에 할당한 우선 순위가 표시됩니다.

  • 선호도 마스크 열 - 일반적으로는 숨겨지는 고급 열입니다. 이 열에는 각 스레드에 대한 프로세서 선호도 마스크가 표시됩니다.다중 프로세서 시스템에서는 선호도 마스크에 따라 스레드가 실행될 수 있는 프로세서가 결정됩니다.

  • 일시 중단됨 열 - 일시 중단 횟수가 표시됩니다. 이 횟수에 따라 스레드를 실행할 수 있는지 여부가 결정됩니다. 일시 중단 횟수에 대한 설명은 이 항목의 뒷부분에 나오는 "스레드 중지 및 재개"를 참조하십시오.

  • 프로세스 이름 열 - 각 스레드가 속하는 프로세스가 표시됩니다. 이 열은 여러 프로세스를 디버깅하는 경우에 유용하지만 일반적으로 숨겨져 있습니다.

중단 모드나 실행 모드에서 스레드 창을 표시하려면

  • 디버그 메뉴에서 을 가리킨 다음 스레드를 클릭합니다.

열을 표시하거나 숨기려면

  • 스레드 창의 맨 위에 있는 도구 모음에서 을 클릭하고 표시하거나 숨길 열 이름을 선택하거나 선택 취소합니다.

활성 스레드를 전환하려면

  • 다음 단계 중 하나를 수행합니다.

    • 스레드를 두 번 클릭합니다.

    • 스레드를 마우스 오른쪽 단추로 클릭하고 스레드로 전환을 클릭합니다.

      노란색 화살표가 새 활성 스레드 옆에 나타납니다. 화살표의 회색 윤곽선은 실행이 중단되고 디버거가 실행된 스레드를 나타냅니다.

스레드를 그룹화하면 테이블에 각 그룹의 제목이 나타납니다.제목에는 "작업자 스레드" 또는 "플래그가 해제된 스레드" 등의 그룹 설명과 트리 컨트롤이 포함됩니다.각 그룹의 멤버 스레드가 그룹 제목 아래에 나타납니다.그룹에 대한 멤버 스레드를 숨기려면 트리 컨트롤을 사용하여 그룹을 축소합니다.

그룹화가 정렬보다 우선하기 때문에 예를 들어 스레드를 범주별로 그룹화한 다음 각 범주 내의 ID로 정렬할 수 있습니다.

스레드를 정렬하려면

  1. 스레드 창의 맨 위에 있는 도구 모음에서 열 위에 있는 단추를 클릭합니다.

    이제 해당 열의 값으로 스레드가 정렬됩니다.

  2. 정렬 순서를 역순으로 바꾸려면 동일한 단추를 다시 클릭합니다.

    목록 맨 위에 나타난 스레드가 이제 맨 아래에 나타납니다.

스레드를 그룹화하려면

  • 스레드 창 도구 모음에서 그룹화 방법 목록을 클릭하고 스레드를 그룹화할 조건을 클릭합니다.

그룹 내에서 스레드를 정렬하려면

  1. 스레드 창의 맨 위에 있는 도구 모음에서 그룹화 방법 목록을 클릭하고 스레드를 그룹화할 조건을 클릭합니다.

  2. 스레드 창에서 열의 맨 위에 있는 단추를 클릭합니다.

    이제 해당 열의 값으로 스레드가 정렬됩니다.

모든 그룹을 확장하거나 축소하려면

  • 스레드 창의 맨 위에 있는 도구 모음에서 그룹 확장 또는 그룹 축소를 클릭합니다.

Visual Studio 2010에서 지정된 문자열과 일치하는 스레드를 검색할 수 있습니다. 스레드 창에서 스레드를 검색하면 창의 열에 검색 문자열과 일치하는 모든 스레드가 표시됩니다.이 정보에는 위치 열의 호출 스택 맨 위에 나타나는 스레드 위치가 포함됩니다.그러나 기본적으로 전체 호출 스택이 검색되지는 않습니다.

특정 스레드를 검색하려면

  • 스레드 창의 맨 위에 있는 도구 모음에서 검색 상자로 이동하고 다음을 수행합니다.

    • 검색 문자열을 입력하고 Enter 키를 누릅니다.

      -또는-

    • 검색 상자 옆의 드롭다운 목록을 클릭하고 이전 검색에서 검색 문자열을 선택합니다.

  • (선택 사항) 검색에 전체 호출 스택을 포함하려면 호출 스택 검색을 선택합니다.

스레드를 중지하면 리소스를 사용할 수 있어도 스레드 실행이 시작되지 않습니다.

네이티브 코드에서는 Windows 함수 SuspendThread와 ResumeThread 또는 MFC 함수 CWinThread::SuspendThreadCWinThread::ResumeThread를 호출하여 스레드를 일시 중단하거나 다시 시작할 수 있습니다. SuspendThread나 ResumeThread를 호출하는 경우 스레드 창에 나타나는 일시 중단 횟수를 변경할 수 있습니다.그러나 네이티브 스레드를 중지하거나 재개하는 경우에는 일시 중단된 횟수를 변경하지 않습니다.네이티브 코드에서는 스레드가 재개되고 일시 중단된 횟수가 0인 경우 이외에는 스레드를 실행할 수 없습니다.

관리 코드에서는 스레드를 중지하거나 재개하면 일시 중단된 횟수가 변경됩니다.관리 코드에서는 중지된 스레드의 일시 중단된 횟수가 1입니다.네이티브 코드에서 중지된 스레드의 일시 중단된 횟수는 0입니다. 단, SuspendThread 호출로 인해 스레드가 일시 중단된 경우는 예외입니다.

참고참고

네이티브 코드에서 관리 코드로의 호출을 디버깅할 때 관리 코드는 이를 호출한 네이티브 코드와 동일한 실제 스레드에서 실행됩니다.네이티브 스레드를 일시 중단하거나 중지하면 관리 코드도 중지됩니다.

스레드 실행을 중지하거나 재개하려면

  • 스레드 창의 맨 위에 있는 도구 모음에서 스레드 중지 또는 스레드 재개를 클릭합니다.

    이 동작은 스레드 창에서 선택되는 스레드에만 적용됩니다.

다중 스레드 프로그램에서 각 스레드에는 자신의 고유한 호출 스택이 있습니다. 스레드 창을 사용하여 편리하게 이러한 스택을 볼 수 있습니다.

스레드의 호출 스택을 보려면

  • 위치 열에서 스레드 위치 옆의 역삼각형을 클릭합니다.

    위치가 확장되어 스레드의 전체 호출 스택이 표시됩니다.

모든 스레드의 호출 스택을 보거나 축소하려면

  • 스레드 창의 맨 위에 있는 도구 모음에서 호출 스택 확장 또는 호출 스택 축소를 클릭합니다.

반응형
반응형

BLOG main image


    대부분 외부 라이브러리(Directx 나 boost 같은)것에 대한 경로를 입력할때 폴더 경로 그대로 입력하면 링크에러가 난다

    정확히 말하자면 어떨때는 나고 어떨때는 안나기도한다, 하지만 된다고 할지라도 나중에 어떤 문제가 발생할지 모름으로

    정확히 해두는 것이 좋다 


    만약 directx 의 include 경로를 폴더경로 그대로인 

    C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include


     라고 입력하면 링크 문제가 새긴다( F7눌러 현재 보이지 않는다 할지라도 나중을 위해  vs 에서 직접 경로를 선택하는

     창을 띄워 선택해

     C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include  과 같은 %로 연결된 형식을

     취해야한다


     왜냐하면 위에서도 언급했찌만 vs가 제대로 경로를 인식하지 못할 가능성이 있기때문이다


     경로 사이사이에 폴더경로처럼 공백이 많은경우 인식을 더더욱 못한다


     하지만 이것은 프로젝트가 많아질 수록 100% 귀찮은 작업인데


     한가지 트릭은 각 프로젝트마다 공통적으로 포함될 경로를 우선 vs의 원하는 디렉토리 경로에


     C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include 처럼 써놓고


     바로옆의 경로를 지정하기위한 창을 누르면 C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include 이경로에 대한


     익스플로러창이뜨면서 그냥 '열기' 버튼을 누르면 자동으로 


     C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Include


     이와같은 경로가 된다


     p.s 원리는 간단함으로 pass






     

반응형
반응형

BLOG main image




여러 쓰래드들이 있다 가정하고, 각 쓰래드들의 첫 진입점에 각각 브레이크포인트를 걸어놓은 후


실행을 시키면 F10만 눌러보아도 알아서 현재 실행되는 쓰래드로 현재 실행시점이 이동되는것을 볼 수있다


이때 비주얼 스튜디오에 쓰래드창을 보면 각 쓰래드의 상태를 볼 수 있으며, 해당 쓰래드의 위치에 마우스를 가져가면 


올려놓은 위치의 쓰래드에대한 call stack 을 보여주며 call stack의 함수를 더블클릭하면 해당 함수로 이동하게 된다



반응형
반응형



windbg 에서보면 현재 실행하는 프로세스에 windbg를 붙여 디버깅할 수 있는데 그때 필요한 것이 일시정지(ctrl+Pause/Break)키 명령이다


비주얼 스튜디오에도 그러한 기능이 있다


'디버그->모두중단' 을 누르거나 또는 ctrl+alt+Pause/Break  를 눌러도 중단이 된다

반응형
반응형

 

Posted by 랩.좀비

안녕하세요. 한 타임 게시를 하지 못한 랩좀비입니다. DOD - Data Oriented Design - 에 대해서 열심히 글을 쓰다가, 실무에 직접 적용해 보지 않고 마냥 좋은 거라고 쓰는 것은 어디서나 찾아 볼 수가 있어서, 지금 회사에서 열심히 DOD를 적용하려고 작업중인 일이 끝나면 회고도 하면서 올리겠습니다. ...언제가 될지는 약속 드릴 수가 없네요. 요즘에 이것 저것 하다보니 적용할 시간이 없더군요. 올해 전반기에는 반드시 할 수 있도록 노력하고 있습니다.

그건 그렇고, 여러분의 프로젝트는 메모리 릭이 얼만큼 발생하십니까? 프로그램이 종료되면 릭이 발생하지 않습니까? 제가 하고 있는 프로젝트도 프로그램이 종료될 때에는 모두 해지가 되어서 메모리릭이 발생하지 않습니다. 하지만, 게임에 들어가면 미친듯이 릭이 발생하고 있었어요. 종료할 때는 메모리릭이 표시되지 않지만 게임중에서는 해지 되지 않는 불편한 상태가 진행되고 있었습니다.

지금까지는 늘어나는 양이 눈에 띄지 않아서 무시해도 될만한 수준이었는데, 최근에 이 문제가 표면에 드러나서 - 무려 시스템 메모리를 2기가 이상까지 올려버려 new에서 badalloc Exception을 보내는 상태까지 가더군요.- 이것을 추적하기 위해 UMDH라는 툴을 사용했습니다. 해당 툴에 대해서 알려주신 모님께 감사를. 프로그래머의 실력은 디버깅에 있다는 생각이 문득 들더군요. 뭐 이건 개인적이 견해이니 넘어가구요...
 
오늘은 UMDH의 맛만 보도록 하겠습니다. 맛만 봐도 어지간한 메모리릭은 잡을 수 있어요. 

UMDH는 메모리를 캡쳐하는 기능을 가지고 있습니다. 그리고 캡쳐된 2개의 로그를 비교해서 변화량을 알려주는 기능도 있지요. 그렇다면 이걸로 어떻게 메모리 릭을 잡느냐... 그냥 게임 시작하면 캡쳐(1)를 하고 여기 저기 돌아다니면서 메모리릭이 발생하는 곳을 찾아서 캡쳐(2)를 한 후, 1번과 2번을 비교해서 그 동안 할당된 로그를 뒤져보는 것입니다. 물론 할당되고 해지된 녀석은 나오지 않습니다. 

UMDH는 WinDBG가 있는 툴셋에 포함되어 있습니다. WinDBG짱좋아요잘쓰면님은나와다른초보 그럼 어떻게 사용하는지 한 번 봐볼까요? 

1. 먼저 어플리케이션을 실행한 다음 UMDH가 적용될 프로그램에 '이놈에게 UMDH를 쓰겠소' 라며 알려줍니다.
저는 개발중인 클라이언트에 적용해 보겠습니다. 파일명만 있으니 보안에 접촉되지 않겠지.우리사장님은대범하시니까.
 

 

 


2. 그리고 캡쳐를 합니다. 캡쳐할 때 프로세스의 ID를 알아와야 하는데 이것은 tlist 명령어를 통해서 알아올 수 있습니다.

이렇게 알아와서

 

 


이렇게 캡쳐를 하지요.

 

 

 
심볼이 없다고 하는데, pdb파일이 있다면 무시하셔도 됩니다만, 정확한 체크를 위해서는 심볼 패스를 지정하는 게 더 좋긴 합니다. 심볼이 없으면 안나오는 정보도 있습니다.

3. 비교를 위해 프로그램을 조금 돌리다가 캡쳐를 합니다.

 

 

 


 

 

4. 이제 비교한 파일을 뱉어 달라고 UMDH에 요청합니다.


 

 


5. 만들어진 log를 열어봅니다. 굉장히 긴 파일이 만들어지는데, 이게 그 동안 할당된 메모리를 나타냅니다.
노란색으로 색칠해진 부분이 16진수로 표현된 바이트입니다.

 

 


이 툴을 이용해서 지난 1주일간 꽤 많은 릭을 잡아 냈습니다. 대부분이 스크립트에서 발생한 것이었지만, 프로그램 쪽에서도 해지 않고 있었던 메모리가 있었지요. UMDH 외에 LeakDiag라는 툴도 있습니다. 이쪽도 한번 구글링해서 테스트 해 보는것도 추천합니다. 무려 메모리변화를 그래프로 출력해 주지요. 하지만 사용해 보니 프로그램의 상태를 툴에서 인젝션할 때 자주 다운되더군요.

암튼, 오늘도 가벼운 주제를 긁고 저는 이만 물러가겠습니다. 좋은 하루 되세요. 
 
 

http://gamedevforever.tistory.com/103

 

 
블로그 이미지

3DMP engines

3D그래픽스 물리 수학, 프로그래밍 GPU Shader 게임엔진 알고리즘 디자인패턴 matlab etc..

 
 
 
 
UMDH는 릭을 발견한곳이 100% 메모리릭이 발생한곳이 아니고 메모리릭일 가능성이 있음을 알려주는 것임으로
 
그것이 릭인지는 개발자가 판단해야한다
 
MFC 에서는 VLD 쓰는게 나을것 같다
 
 
 
cmd 명령창에서 "GFlags -I 응용프로그램이름.exe +ust"  로 유저스택 추적을 설정
 
시스템의 환경변수는 아래처럼 설정한다
 
"cmd 에서 Set _NT_SYMBOL_PATH=c:\Window\symbols;응용프로그램심볼경로"
 
를 설정해주면 되고 아래 소개된글에서는 tlist 로 cmd 에서 프로세스ID를 알아보지만 
 
작업관리자 창에서도 PID열을 추가하면 해당 응용프로그램의 프로세스ID를 알 수 있기때문에
 
캡쳐하는 수고를 덜 수있다.
 
사용하는 법은 아래 글을 참고하면 되고 약간 설명을 추가하자면
 
 
결과 log파일은 
 
+    523(  523-  0)        10 allocs                    BackTraceCFF
+      10(  10 -  0)         BackTraceCFF             allocations
 
처럼 중간에 나오는데 이것은
 
523바이트의 메모리를 할당한것이며, 10회의 메모리 할당이 있었는데 아직 해제되지 않았다는 뜻이다.
 
 
 
 

 

반응형
반응형

http://www.reversecore.com/29


Process Explorer



Windows 최고의 프로세스 관리 도구 Process Explorer 입니다.

https://technet.microsoft.com/en-us/sysinternals/bb896653.aspx

저 유명한 sysinternals (현재는 MS에 인수되었음) 의 Mark Russinovich 씨가 만든 프로세스 관리 유틸리티입니다.

이분은 Windows 운영체제에 대해서 매우 해박한 지식을 갖고 있으며,
유용한 유틸리티(FileMon, RegMon, TcpView, DbgView, AutoRuns, Rootkit Revealer, etc) 들을 만들어 공개하였습니다.

언젠가 한번은 FileMon 과 RegMon 의 소스 코드를 공개하신적이 있습니다. (지금은 없어졌지요.)
Windows 운영체제 초창기에 (맨땅에 헤딩하던) 시스템 드라이버 개발자들에게 있어서 
그 소스들은 그야말로 사막의 오아시스 같은 존재였습니다.

각설하고 Process Explorer 의 실행화면을 보실까요.


< Fig.1 - Process Explorer 실행화면 >

Windows 작업관리자와는 비교 할 수 없는 아주 뛰어난 화면 구성을 보여주고 있습니다.

화면 위의 좌측에는 현재 실행중인 프로세스들을 Parent/Child 의 트리 구조로 표시하고 있습니다. (무려 아이콘 까지!!!)
우측에는 프로세스 각각의 PID, CPU 점유율, 등록정보 등을 보여줍니다. (Option 을 통해 더 추가 가능)

화면 아래(욥션)에는 선택된 프로세스에 매핑된 DLL 정보 또는 해당 프로세스에서 오픈한 object handle 을 표시합니다.



구체적으로 뭐가 좋은거죠?


좋아 보이기는 하는데 구체적으로 뭐가 좋은건지 궁금하시죠?

저는 리버싱 할 때 항상 Process Explorer 를 같이 띄워놓고 합니다.
제가 Process Explorer 를 좋아하는 이유는 이렇습니다.

  • Parent/Child 프로세스 트리 구조
  • 프로세스 실행/종료시 각각의 색깔(초록/빨강)로 표시
  • 프로세스 suspend 기능 (실행 중지)
  • 프로세스 종료(kill) 기능 (Kill Process Tree 기능 지원)
  • DLL/Handle 검색 (프로세스에 인젝션된 DLL 검색 또는 특정 파일을 오픈한 프로세스 검색)

  • 이외에도 다양한 기능들이 있습니다만, 위 기능들이 특히 리버싱 할 때 많이 사용되는 기능들입니다.
    그리고 꾸준한 업데이트(버그 수정, 기능 추가)도 큰 장점입니다.



    sysinternals


    sysinternals 홈페이지에 가보시면 Process Explorer 의 미니 콘솔 버전들이 있습니다. 
    (PsKill, PsSuspend, PsList, etc)

    이 유틸들도 받아서 실행해 보세요. Process Explorer 의 기능을 축소시킨 멋진 콘솔 버전 프로그램들입니다.

    리버싱을 위해 Windows 내부구조를 공부하시는 분들께서는 간단히 이런 콘솔 프로그램을 따라 만들어 보세요.
    프로세스와 DLL 등에 대한 이해를 높일 수 있습니다.
    (제 경험상 따라 만드는 방법이 실력 향상을 위한 가장 좋은 방법입니다. ^^)



    이상으로 최고의 프로세스 관리 유틸리티 Process Explorer 에 대한 소개를 마칩니다.








    http://shinyhappy.tistory.com/25



    실행 중인 프로세스를 확인하고 관리하는데 보통 윈도우 작업관리자를 사용합니다.

    그러나 작업관리자로는 실행 중인 프로세스에 대한 충분한 정보를 얻을 수 없는 경우가 있습니다.

    실행 중인 프로세스에 대한 모든 정보를 알고 싶을 때는 MS의 Process Explorer를 사용합니다.

    Process Explorer는 Sysinternals에서 제작 배포하는 도구였으나 MS가 Sysinternals를 인수하여 Sysinternals 홈페이지는 MS Technet 사이트로 연결됩니다.

    Sysinternals 에서는 Process Explorer 이외에도 AutoRuns, Regmon, Filemon 같은 유용한 도구를 Free로 다운로드할 수 있습니다.

    [Process Explorer 다운로드]



    Process Explorer 실행

    다운로드 후에 압축을 풀고 "procexp.exe" 파일을 실행한 후 사용권계약서에 동의합니다.

    사용자 삽입 이미지

    Process Explorer 실행


    Process Explorer의 기본화면 입니다.

    실행중인 프로세스의 이름, CPU 점유율, 설명, 회사 이름이 기본으로 표시됩니다.
    Tree를 이용하여 프로세스 실행의 계층 관계를 확인할 수 있습니다.

    사용자 삽입 이미지

    Process Explorer


    옵션에서 Replace Task Manager 메뉴를 체크하면 윈도우 작업관리자를 대체합니다.

    이 경우 유명한 Ctrl+Alt+Delete 키를 누르게 되면 작업관리자 대신에 Process Explorer가 실행됩니다.

    사용자 삽입 이미지

    작업관리자 대체


    View 메뉴에서 Select Column을 선택하면, 추가 정보를 확인할 수 있습니다.

    사용자 삽입 이미지

    컬럼 선택



    여러가지 기능이 있지만 주로 사용하는 것은 Image Path와 Command Line 입니다.

    • Image Path : 실행 중인 프로세스의 전체 경로를 표시합니다.
    • Command Line : 실행 중인 프로세스의 명령줄 옵션을 표시합니다.

    사용자 삽입 이미지

    컬럼 선택 대화상자


    선택한 컬럼이 적용되었습니다. Path에는 실행 중인 프로세스의 전체 경로가 표시되고, Command Line에는 옵션 및 스위치 등의 명령줄이 표시됩니다.

    사용자 삽입 이미지

    컬럼 적용


    실행 중인 프로세스를 강제로 종료하고 싶을 때는 프로세스를 선택한 후 마우스 오른쪽 버튼 메뉴에서 Kill Process을 선택합니다.

    응답이 없는 프로그램, CPU 점유율이 지나치게 높은 프로세스, 악성코드 및 스파이웨어 제거에 유용하게 사용할 수 있습니다.

    Kill Process Tree 메뉴는 종속 관계로 실행된 모든 프로세스를 종료할 수 있습니다. Hooking을 하거나 종속관계로 실행되는 악성코드 제거에 유용하게 사용할 수 있습니다.

    사용자 삽입 이미지

    프로세스 종료


    반응형
    반응형

    http://jkmoon.tistory.com/76

    성능모니터 로그 적용

    특정시간에, 시스템의 성능에 영향을 주는지는 확인하기 위하여 성능모니터 로그를 적용하여, 로그수집

    하는 방법을 포스팅 하도록 하겠습니다.

       

    [환경]

    Windows Server 2008R2 EE

       

    1. 시작 > 실행 > perfmon 실행하신 후 성능모니터에 적용 할 카운터를 추가 합니다.

       

    2. processor 성능확인을 위해 아래와 같이 카운터를 추가하였습니다.

       

    3. 카운터를 적용한 설정을 다른이름으로 저장 합니다.

       

    4. Cpu성능.htm 으로 저장 합니다.

       

    5. 새로 만들기 > 데이터 수집기 집합 적용합니다.

       

    6. 이름은 임의대로 적용하시면 됩니다. 다음

       

    7. 데이터를 저장할 위치를 선택합니다.

       

    8. 저장 후 닫기 선택 합니다. > 마침

       

    9. CPU성능 > 속성을 선택 합니다.

       

    10. 일정을 확인 하신 후 아래처럼 시작 시간을 적용합니다.

       

       

    11. 시스템 모니터 로그 > 속성을 열어 필요한 설정을 합니다.

       

    12. 샘플 간격을 15초로 설정 하겠습니다. 15초마다 성능을 취합 합니다.

       

    13. 로그파일의 이름과 형식을 설정합니다.

       

    14. 설정된 시간에 맞게, 성능모니터에서 로그 수집이 진행 됩니다.

       

       

    15. Explore창을 여러 개 띄운 후 CPU 사용률을 증가 시켜봅니다.

    그리고, 성능로그 수집을 종료한 후 로그 분석을 진행 하도록 하겠습니다.

       

    16. 로그파일을 더블 클릭하여, 수집된 로그를 토대로 CPU 성능을 확인 합니다.

       

    [참조사이트]

    Windows 성능 모니터

    http://technet.microsoft.com/ko-kr/library/cc749249(WS.10).aspx

    반응형
    반응형


    고급 디버깅은 꼭 필요하지는 않지만(기본 디버깅 방법만 알아도 디버깅 할 수 있지만) 알아 두면

     

    디버깅하는데 도움이 되는 것들에 대해 다루었습니다.

     

     

    집에서 시간이 더 많음에도 불구하고 공부는 더 안되는군요...

     

    세미나 PPT 내용도 예전보다 나아지지는 못할 망정 부실해 지는거 같습니다.

     

    빨리 멤버십 복귀해서 많이 부족하지만 카페북을 빨리 마무리 하고, 스피드하게 크랙미를 끝내도록

     

    노력하겠습니다.

     




    [디버깅][windbg] 4차 세미나 ppt - 고급디버깅_김현철.pptx


    반응형
    반응형

    강좌글 올린 것 중 가장 많이 발생하는 경우인 잘못된 메모리 사용, 메모리 누수에 대한 상황을 어떻게

     

    해결해야 되는지에 대해 준비했습니다.

     

     

    시작발표, 갑작스러운 이사 때문에 정신 없어서 시그 활동을 열심히 못한 거 같습니다.

     

    다시 달려야 하는데, 역시 집에서 공부하기 힘드네요...;; 


    반응형
    반응형

    http://cafe.naver.com/totallab/560





    참고 : 'WinDbg로 쉽게 배우는 Windows Debugging' 에이콘 출판사

     

    =============================================================================================================

     

    크래시 덤프를 확보하면 WinDbg의 [File] 메뉴에서 [Open Crash Dump…]를 선택해(단축키 : Ctrl+D) 덤프 파일을 열수 있습니다.

     

    <?xml:namespace prefix = v /><?xml:namespace prefix = v /><?xml:namespace prefix = o /><?xml:namespace prefix = o />

     

    파일 대화상자가 나타나면 덤프 파일이 있는 경로로 찾아가서 파일을 열거나 WinDbg UI에 드래그 앤 드롭으로 파일을 끌어다 놓아 열 수도 있습니다.

     

    덤프 파일을 열면 다음과 같은 메시지가 나타납니다.

     

     

     

    보통 사람들은 덤프를 열고 이 메시지를 본 후에 더 이상 무엇을 해야 할지 몰라서 WinDbg를 종료해 버립니다덤프를 분석하는 방법을 조금만 알면 손쉽게 문제의 원인을 찾아서 수정할 수 있습니다.

    메시지에서 주의 깊게 봐야 하는 부분은 첫 번째 덤프 파일 경로와 어떤 유형의 덤프인지 표시하는 부분입니다. ‘User Mini Dump File with Full Memory’라고 나오는데전체 메모리 미니 덤프 파일은 응용프로그램이 사용하던 모든 메모리가 유효하다고 알려줍니다일반적으로 이것을 전체 덤프라고 합니다미니덤프는 레지스터와 스택메모리 포인터만 유효한데전체 덤프와 같이 프로세스가 사용하면 메모리가 모두 파일로 만들어지지 않으므로 미니 덤프에 포함된 메모리의 일부만 확인할 수 있습니다.덤프 종류에 따른 메시지를 정리하면 다음과 같습니다.

     

    -       전체 덤프 : User Mini Dump File with Full Memory : Only application data is available.

    -       미니 덤프 : User Mini Dump File : Only Registers, stack and portions of memory are available.

     

    분석을 시작할 때 미니 덤프인지 전체 덤프인지 확인을 해야 어느 부분까지 분석할 수 있는지 알 수 있기 때문에 잘 봐두는게 좋습니다.

     

    두 번째로는 덤프가 발생한 운영체제 종류를 표시합니다제 운영체제는 윈도우 7이지만 용량관계상 전체 덤프가 생성되지 않아 예제로 제공하는 덤프 파일을 열었는데예제 파일을 만든 컴퓨터는 윈도우 XP이며서비스 팩 2환경에서 작업했다는 것을 알 수 있습니다.

    그 다음은 덤프가 발생한 시간을 표시합니다문제가 발생한 시간은 문제를 분석할 때 중요한 단서가 되는 경우가 많습니다.

     

    그 다음에 나오는 Process Uptime은 프로세스 실행 후 얼마나 오랫동안 동작하고 있었는지 알 수 있는 정보입니다이것을 통해 예제 같은 경우에는 1 29초만에 문제가 발생했다는 것을 알 수 있습니다.

     

    다섯 번째는 .ecxr 명령을 통해 저장된 예외 정보에 접근할 수 있다는 메시지 입니다어떤 프로세스에 예기치 않은 오류가 발행하면 덤프 파일에는 예외에 대한 정보가 저장되는데WinDbg를 이용하여 예외 정보를 읽고 예외가 발생한 당시의 상태로 돌려놓고 분석을 할 수 있게 합니다이와 같이 WinDbg가 보여주는 메시지에 분석을 어떻게 해야 하는지 제시하는 내용들이 자주 나옵니다따라서 WinDbg의 메시지를 주의 깊게 읽어보고 WinDbg에서 하라는 대로 하는 것이 좋습니다WinDbg가 하라는 대로 따라 하도록 합니다.

     

    , .ecxr 명령을 내리면서 디버깅을 시작합니다. .ecxr을 잘 모른다면 WinDbg의 Help메뉴를 열고 찾아 보는 것이 가장 좋습니다사실 WinDbg 도움말은 디버거 사용법뿐만 아니라 디버깅 스킬에 대한 최고의 안내서 입니다내용도 자세하고 광범위해 도움말만 모두 이해한다면 WinDbg와 디버깅의 달인이 될 수 있다고 하니WinDbg 도움말을 옆에 끼고 살아야겠습니다.

     

    .ecxr 명령을 조금만 설명하면 예외가 발생한 상황에 저장된 컨텍스트 레코드를 보여주고 디버거가 해당 내용을 참조하게 하는 명령입니다.

     

    컨텍스트 레코드란단순하게 설명하면 CPU 레지스터 셋을 의미합니다다시 말해서 예외가 발생했을 당시에 저장된 레지스터 셋을 보여주고 이 상태로 되돌려 줍니다.

     

     

    이제 콜 스택을 보면 문제가 발생한 흐름을 알 수 있습니다. k 명령을 수행해 콜 스택을 살펴 보도록 하겠습니다.

     

     

    윗부분이 마지막에 호출된 부분이므로 MyApp 내부에서 문제가 발생했을을 알 수 있었지만어느 함수에서 문제가 발생했는지 알 수 없습니다이 상태에서 MyApp에 대한 심볼만 맞추면 어떤 함수이고어느 소스코드의 몇 번째 라인이 문제인지 찾을 수 있습니다.

     

    다음 강좌에서는 모듈 정보 보기와 심볼 맞추기에 대해서 설명하도록 하겠습니다.

    반응형
    반응형

    http://process3.blog.me/20065867268



    `WinDBG로 Deadlock 알아내기

    IT이야기 2009/05/31 21:22
    대학에서 운영체제 시간에 Deadlock에 대해서 배울 때, 많이 거론되는 것이 Dijkstra의 '식사하는 철학자' 일 것이다. 
    멀티 쓰레딩 프로그래밍을 하다 보면 아주 많은 주의를 기울여야 할 Deadlock 문제. 
    다양한 deadlock 문제 중에 윈도우 프로그래밍의 critical section에서 야기될 수 있는 deadlock을 WinDBG를 사용해서 발견하는 방법을 설명하려고 한다. 
    멀티쓰레딩 프로그램에서 hang이 발생하면 우선 deadlock을 의심해볼 수 있다. 
    처음으로 할 일은 hang dump를 수집하는 것이다. 
    windbg의 attach process 기능을 사용하던지, ADPlus나 UserDump 프로그램을 사용해서 응답하지 않는 프로그램의 hang dump를 수집한다. 
    hang dump는 약간의 시차(한 10초 정도)를 두고 3번 정도 반복해서 만드는 것이 좋다. 
    dump가 생성되면 windbg를 사용해서 디버깅을 시작한다. 
    dump 파일을 open 하고 난 뒤, command line에 '!locks'라고 친다. 
    user mode 디버깅에서는 locks는 ntsdexts.locks와 동일한 명령이다. 
    이 명령은 ntdll.dll에 있는 RtlInitializeCriticalSection에 의해서 초기화된 critical section 객체의 정보를 쭉 보여준다. 

    =====================================================


    0:000> !locks

    CritSec w3svc!g_pWamDictator+a0 at 68C2C298
    LockCount          0
    RecursionCount     1
    OwningThread       d1
    EntryCount         1
    ContentionCount    0
    *** Locked

    CritSec SMTPSVC+66a30 at 67906A30
    LockCount          0
    RecursionCount     1
    OwningThread       d0
    EntryCount         1
    ContentionCount    0
    *** Locked


    =====================================================

    여 기에 아무런 옵션이 없으면 현재 프로세스에 속한 critical section 객체만을 보여주고, 옵션으로 -v를 붙이면 프로세스 밖에 있는 critical section 객체도 보여준다. '-o' 옵션은 Windows XP와 그 이후의 운영체제만 지원하는 것으로 orphaned information(유효하지 않은 critical section을 가르키고 있는 포인터)만을 보여준다. 
    locks 명령 말고도 비슷한 모양으로 정보를 보여주는 명령어는 !critecs, !cs 등이 있다.

    이 위의 출력물에 대한 의미는 다음과 같다. 

    • Windows XP와 그 이전 것들
      • LockCount 필드는 이 critical section으로 진입하기 위한 EnterCriticalSection()을 호출한 thread의 수에서 하나를 뺀 것과 같다. 왜 하나를 빼야 하냐면, 이 필드는 -1을 unlock 상태로 표시하고 EnterCriticalSection()이 호출될 때마다, 하나씩 증가하기 때문이다. 나중에 LeaveCriticalSection()이 호출되면 하나씩 감소시킨다. 예를 들어, 만약 이 값이 3이라면 하나의 thread는 이 critical section에 진입한 상태이고, 3개의 다른 thread들이 이 곳에 진입하기 위해서 기회를 노리고 있다는 의미이다. 
      • RecursionCount 필드는 critical section에 진입한 thread가 다시 EnterCriticalSection()을 몇 번 더 호출하고 있는지를 나타낸다. 
      • EntryCount 필드는 critical section에 진입하지 못한 thread가 몇 번이나 EnterCriticalSection()을 호출하고 있는지를 나타낸다. 
      • CritSec w3svc!g_pWamDictator+a0 at 68C2C298에서 at 다음에 있는 숫자는 critical section의 핸들이다. 
      • Owning thread는 말 그대로 이 critical section 객체를 현재 가지고 있는  thread이다. 

    • 그 이후 것들(Windows Server 2003 SP1과 그 이후것들)은 'Debugging Tools for Windows'의 Help에 Display a Critical Section 편을 보면 자세히 나와 있다.


    Deadlock에 빠진 것이라면, !locks 명령어를 실행했을 때, LockCount가 1 이상인 것들이 하나 이상 존재해야 한다.  
    만약 그렇다면 이 thread들의 call stack을 훑어 봐야 한다. 
    call stack을 보면 top 언저리에 ntdll!RtlpWaitForCriticalSection+0x132와 비슷하게 보이는 frame이 존재하는데 이 함수의 첫번째 인자가 그 thread가 지금 기다리고 있는 critical section의 핸들이다. 이 핸들을 !locks으로 출력됐던 결과에서 봤을 때, critical section을 가지고 있는 두 놈이 서로의 것을 기다리고 있다면, 100%입니다.

    반응형
    반응형

    http://process3.blog.me/20065867268

    WinDbg를 이용해서 Critical Section 추적해 보기. 

    2009/04/17 17:16

    복사http://process3.blog.me/20065867268


     최근에 덤프를 하나 분석하고 있는데 동기화 관련해서 이슈가 발생한것 같습니다. criticalsection 관련 WinDbg 명령하나를 정리합니다. 필요하신 분들 참고하세요~

     

    1) 문제가 있는 CriticalSection 오브젝트가 있는지 확인한다.

     

    0:019> !locks -o
    Looking for orphaned critical sections

    CritSec at 100a4824 could not be read
    Perhaps the critical section was a global variable in a dll that was unloaded?

    CritSec at 100a4648 could not be read
    Perhaps the critical section was a global variable in a dll that was unloaded?

    CritSec at 100a47e0 could not be read
    Perhaps the critical section was a global variable in a dll that was unloaded?

    CritSec at 100a4660 could not be read
    Perhaps the critical section was a global variable in a dll that was unloaded?

    Scanned 650 critical sections

     

    총 650개 critical sections 중에 약 4개가 문제가 있는것 같습니다.

     

    2)!cs 명령을 통해서 좀 더 자세하게 확인해 보겠습니다.

    0:019> !cs -l
    -----------------------------------------
    DebugInfo          = 0x00154990
    Critical section   = 0x008f211c (+0x8F211C)
    LOCKED
    LockCount          = 0x0
    OwningThread       = 0x000001c0
    RecursionCount     = 0x1
    LockSemaphore      = 0x0
    SpinCount          = 0x00000000
    -----------------------------------------
    DebugInfo          = 0x001497a0
    Critical section   = 0x008f335c (+0x8F335C)
    LOCKED
    LockCount          = 0x0
    OwningThread       = 0x00000204
    RecursionCount     = 0x1
    LockSemaphore      = 0x0
    SpinCount          = 0x00000000
    -----------------------------------------
    DebugInfo          = 0x00149840
    Critical section   = 0x008f304c (+0x8F304C)
    LOCKED
    LockCount          = 0x0
    OwningThread       = 0x00000208
    RecursionCount     = 0x1
    LockSemaphore      = 0x0
    SpinCount          = 0x00000000
    Cannot read structure field value at 0x100a4828, error 0
    Cannot determine if the critical section is locked or not.
    -----------------------------------------
    Critical section   = 0x100a4824 (+0x100A4824)
    DebugInfo          = 0x0015a198
    Cannot read structure field value at 0x100a464c, error 0
    Cannot determine if the critical section is locked or not.
    -----------------------------------------
    Critical section   = 0x100a4648 (+0x100A4648)
    DebugInfo          = 0x0015a2d0
    Cannot read structure field value at 0x100a47e4, error 0
    Cannot determine if the critical section is locked or not.
    -----------------------------------------
    Critical section   = 0x100a47e0 (+0x100A47E0)
    DebugInfo          = 0x0015a2f8
    Cannot read structure field value at 0x100a4664, error 0
    Cannot determine if the critical section is locked or not.
    -----------------------------------------
    Critical section   = 0x100a4660 (+0x100A4660)
    DebugInfo          = 0x0015a320
    -----------------------------------------
    DebugInfo          = 0x001676d8
    Critical section   = 0x009609ac (+0x9609AC)
    LOCKED
    LockCount          = 0x0
    OwningThread       = 0x0000064c
    RecursionCount     = 0x1
    LockSemaphore      = 0x0
    SpinCount          = 0x00000000
    -----------------------------------------
    DebugInfo          = 0x001771e8
    Critical section   = 0x00978664 (+0x978664)
    LOCKED
    LockCount          = 0x0
    OwningThread       = 0x000001c0
    RecursionCount     = 0x1
    LockSemaphore      = 0x0
    SpinCount          = 0x00000000
    -----------------------------------------
    DebugInfo          = 0x001478b0
    Critical section   = 0x00978684 (+0x978684)
    LOCKED
    LockCount          = 0x0
    OwningThread       = 0x000001c0
    RecursionCount     = 0x1
    LockSemaphore      = 0x0
    SpinCount          = 0x00000000

    ...

     

    이 프로그램이 생각보다 많은 Critical Section 오브젝트를 사용하고 LOCKED 되어 있는것도 많습니다.

    또한 Looking for orphaned critical sections(소유자가 없는 Critical Section 오브젝트)도 4개나 있습니다.

     

    3) 소유주가 없는 Critical Section 오브젝트를 좀 더 조사해 봅시다.

    0:019> !cs -o 0x100a4648 
    Cannot read DebugInfo adddress at 0x100a4648. Possible causes:
     - The critical section is not initialized, deleted or corrupted
     - The critical section was a global variable in a DLL that was unloaded
     - The memory is paged out

    Cannot read structure field value at 0x100a464c, error 0
    Cannot determine if the critical section is locked or not.
    -----------------------------------------
    Critical section   = 0x100a4648 (+0x100A4648)
    DebugInfo          = 0x00000137

     아래 3가지 경우중에 하나이면 소유주가 없는  Critical Section 오브젝트가 생겨서 크래쉬가 발생하고 문제 해결이 정말 어려워지는 버그가 발생합니다.

     - 초기화 되지 않았거나 지워졌거나 오염된 경우(The critical section is not initialized, deleted or corrupted)
     - DLL에서 전역변수로 Critical Section 오브젝트가 선언되었는데 DLL이 언로드된 경우 (The critical section was a global variable in a DLL that was unloaded)
     - 메모리가 페이지 아웃된 경우 (The memory is paged out)

     

     

    [Critical section 에서 문제가 발생할 수 있는 상황 정리]

    1. InitializeCriticalSection(...) 함수를 호출 하지 않았다.
    2. 여러번 InitializeCriticalSection(...) 호출되었고 DeleteCriticalSection(...)이 한번도 호출되지 않은 상황에서 다시 초기화된 경우
    3. DeleteCriticalSection(...) 호출되었다 그러나 Critical section  오브젝트가 계속해서 참조되고 사용된다.
    4. 스레드에서 EnterCriticalSection(...) 호출되고 사용된다. 그러나 LeaveCriticalSection(...).함수를 호출하지 않았다. 그리고 다른 스레드에서 EnterCriticalSection(...).함수를 호출해서 사용한다.

    즉, 메모리에 선언되지 않았거나 메모리에서 지워진  Critical section   오브젝트를 사용하면 큰일 난다

     

    1)초기화 하지 않은 Critical section 오브젝트

    // Not initilize the Critical section.
    // Global variable
    CRITICAL_SECTION CriticalSection; 
    int _tmain(int argc, _TCHAR* argv[])
    {
        //InitializeCriticalSection(&CriticalSection);
        EnterCriticalSection(&CriticalSection);
      
        LeaveCriticalSection(&CriticalSection);

        DeleteCriticalSection(&CriticalSection);
        return 0;
    }

     

    2)삭제된 Critical section 오브젝트 참조하기
    // Global variable
    CRITICAL_SECTION CriticalSection; 
    DWORD WINAPI ThreadProc( LPVOID lpParameter )
    {
     //InitializeCriticalSection(&CriticalSection);
        // Request ownership of the critical section.
        EnterCriticalSection(&CriticalSection); 
        // Release ownership of the critical section.
        LeaveCriticalSection(&CriticalSection);
     DeleteCriticalSection(&CriticalSection);
     return 0;
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
        // Initialize the critical section one time only.
        InitializeCriticalSection(&CriticalSection);
     CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
      
     Sleep(3000);
     EnterCriticalSection(&CriticalSection);
     LeaveCriticalSection(&CriticalSection);
     DeleteCriticalSection(&CriticalSection);
     return 0;
    }


    출처 : 다년간의 프로그램밍 삽질(경험)->요즈음 나를 괴롭히는 버그... ㅠㅠ 그리고 구글 검색으로부터...


    반응형
    반응형


    블로그 이미지

    3DMP engines

    3D그래픽스 물리 수학, 프로그래밍 GPU Shader 게임엔진 알고리즘 디자인패턴 matlab etc..

    by 송정헌



    (x64 OS에서) !wow64exts.sw 를 실행하면 x86 모드로 바뀐다  또한 명령입력창이 0:007:x86> 으로 x86 모드를 나타낸다


    다시 !wow64exts.sw을 실행하면 다시 x64모드로 바뀐다  또한 명령 입력창이  0:007> 으로(x64) 바뀌는 것을 알 수있다.





    wow64.dll 사용하는 프로세스 덤프 파일 디버깅[섭군]

    최근 64비트 OS에서 실행중인 32비트 프로세스가 행이 걸린적이있었습니다. 그래서 일단 userdump 로 풀덤프를 떴습니다.

    해당 덤프를 VS 로 보면 wow64cpu.dll 내부 함수에서 콜스택이 멈춰있게 나오더군요. 마지막 콜스택이 wow64cpu!CpupSyscallStub+0x9 였습니다.


    해당 함수를 구글에서 검색하니 바로 나오더군요(http://blogs.msdn.com/ntdebugging/archive/2008/06/03/how-to-debug-wow64-applications.aspx )


    그전에는 저게 멀까 멀뚱멀뚱 했습니다. ㅠ_ㅠ;


    결론적으로는 wow64exts.dll 을 활용해서 디버깅을 해야한다입니다.


    실제적으로는 아래 두명령어만 있으면 끝이더군요.


    !wow64exts.kb : 콜스택을 x86 모드로 변환해서 보여줍니다.


    !wow64exts.sw : 디버깅 모드를 x86모드로 변환합니다. (이후 k 를 입력하면 정상적인 x86 콜스택이 정상적으로 보입니다.)


    아래는 예입니다.

    사용자 삽입 이미지

    콜스택이 wow64cpu!CpupSyscallStub+0x9 에서 다 멈춰있습니다.



    (windbg 명령어 입력란에 !wow64exts.sw 명령을 입력)


    사용자 삽입 이미지


    (잘 안보이시면 클릭하셔서 보세요)


    !wow64exts.sw 를 사용여 x86모드로 전환 후 콜스택을 확인하였습니다. 소스까지 나오는군요.


    원인은 맨위 스레드가 메인스레드로 아래 두스레드가 종료되기를 기다리고있습니다.


    두번째 스레드가 동기화 객체 획득 후 Sleep(INFINITE) 을 하고있습니다.


    세번째 스레드가 동기화 객체 획득을 하려고 대기중입니다.


    알고나니 정말 편하군요. ㄷㄷ


    반응형
    반응형

    http://technet.microsoft.com/en-us/sysinternals/bb896653



    Process Explorer v15.23

    By Mark Russinovich

    Published: October 3, 2012

     Download Process Explorer
    (1.0 MB)

    Rate:  
     

    Introduction

    Ever wondered which program has a particular file or directory open? Now you can find out. Process Explorer shows you information about which handles and DLLs processes have opened or loaded.

    The Process Explorer display consists of two sub-windows. The top window always shows a list of the currently active processes, including the names of their owning accounts, whereas the information displayed in the bottom window depends on the mode that Process Explorer is in: if it is in handle mode you'll see the handles that the process selected in the top window has opened; if Process Explorer is in DLL mode you'll see the DLLs and memory-mapped files that the process has loaded.Process Explorer also has a powerful search capability that will quickly show you which processes have particular handles opened or DLLs loaded.

    The unique capabilities of Process Explorer make it useful for tracking down DLL-version problems or handle leaks, and provide insight into the way Windows and applications work.

    Related Links

    • Windows Internals Book
      The official updates and errata page for the definitive book on Windows internals, by Mark Russinovich and David Solomon.
    • Windows Sysinternals Administrator's Reference
      The official guide to the Sysinternals utilities by Mark Russinovich and Aaron Margosis, including descriptions of all the tools, their features, how to use them for troubleshooting, and example real-world cases of their use.

    Download 

    No

    Download Process Explorer
    (1.0 MB)

     

    Run Process Explorer now from Live.Sysinternals.com

    Download

    No


    Download Process Explorer

    (1.0 MB)


    Run Process Explorer
     now from Live.Sysinternals.com

    Runs on:

    • Client: Windows XP and higher (Including IA64).
    • Server: Windows Server 2003 and higher (Including IA64).

    Installation

    Simply run Process Explorer (procexp.exe).

    The help file describes Process Explorer operation and usage. If you have problems or questions please visit the Sysinternals Process Explorer Forum.

    Learn More

    Here are some other handle and DLL viewing tools and information available at Sysinternals:

    반응형
    반응형

    또 갑자기 공부가 안되는 시기인건지... 아무것도 손에 안잡히는 군요.. 이럴땐 책을 보는게 최선인거 같습니다.
    그래서 WinDbg 책을 폈는데.. 괜찮은 내용인거 같아서 바로정리.. ^^;
    ===========================================================================
    이번에 알아볼 내용은 GFlags를 사용해 힙 영역에서 발생할 수 있는 문제점을 탐지해 내는 방법입니다.

    간단한 툴 소개가 될꺼같으니.. 짤막하게 하겠습니다.
    일단 문제가 되는 소스코드를 보시겠습니다.

    소스코드를 보시면 7번째 줄에서 malloc을 사용해 힙 영역에 메모리를 할당 받고 있습니다.
    그리고 14번째 줄에서 할당받았던 메모리를 해제해 주고 있습니다.
    그런데 16번째 줄에서 해제한 메모리에 값을 쓰고 있습니다.

    이건 분명 문제가 있는 코드입니다. 해제한 힙 영역에 데이터를 쓴다는 것은 지금 당장은 문제가 되지 않지만 계속 프로그램을 사용하다보면 언젠간 문제가 생길것 입니다.

    일단 코드 실행을 해보겠습니다.

    정상적으로 종료가 되며 오류창이 뜨거나하는 그런 현상도 나타나질 않습니다.

    아마 이대로 배포를 하게 된다면.. 언제일진 몰라도 문제가 발생하겠죠.

    이제 GFlags라는 툴을 사용해 이러한 잠재적인 취약점을 탐지해보도록 하겠습니다.
    해당 툴은 WinDbg를 설치하게 되면 같은 폴더에 존재합니다. MS에서 무료배포 해주는 것이지요.


    이제 툴을 켜줍니다.

    세번째 Image File이라는 탭으로 오게되면 위와같은 화면이 나오게 됩니다. 
    두개 빼곤 전부 비활성화된 상태인데 Image에 실행파일 명을 쳐주고 탭을 누르면 활성화 되게 됩니다.

    먼저 전 gflags.exe 있는 폴더에 테스트해볼 프로그램(위 소스를 컴파일해서 만든 실행파일..)을 넣어두고 실행파일 명을 치고 Tab을 눌렀습니다.

    Enable page heap부분에 체크를 해주셔야합니다.
    저 부분을 체크해주면 할당한 버퍼보다 더 많이 쓰려고 하거나 해제한 메모리를 재사용하려는 부분은 감지할수 있습니다.
    그냥 실행시켰을 때는 아무런 문제가 발생하지 않는데 gflags를 사용해 실행시켰을 경우 오류가 날것입니다.

    저 같은 경우는 오류가 날 경우 바로 WinDbg로 연결되도록 해놓았기 때문에 오류창은 안뜰것입니다.

    이제 저 상태에서 Launch를 누르게 되면 프로그램이 실행될 것입니다.
    그 상태에서 진행해보겠습니다.

    아까는 아무런 문제가 없던 프로그램이 갑자기 오류가 생기면서 디버거에 연결됬습니다.
    파일을 보니 Malloc.exe 네요. 오류발생 원인은 잘못된 메모리에 접근을 한거 같습니다.

    일단 해당 어셈코드를 보니 0x01600f98에 접근을 못하고 있는건데.. 이 내용을 보고는 일단 문제가 있다는 것은 알수있는데
    무엇때문인지는 알 수 없습니다. 그래서 해당 메모리의 특성을 봐보도록 하겠습니다.

    명령어는 !address를 사용해도 되고 !vprot를 사용해도 됩니다. 전 !vprot를 사용했습니다.

    보호상태를 보니 페이지에 접근할 수 없는 상태입니다. 즉, 메모리가 해제된 곳이라는 것을 알 수 있습니다.

    결론은 GFlags를 사용해 자기가 만든 프로그램을 배포전에 한번쯤 테스트를 해보는 것도 좋은 습관일꺼 같습니다.

    반응형
    반응형

    블로그 이미지

    3DMP engines

    3D그래픽스 물리 수학, 프로그래밍 GPU Shader 게임엔진 알고리즘 디자인패턴 matlab etc..

    by 송정헌




    64bit 인 경우 C:\Windows\SysWOW64\%LOCALPPDATA%\CrashDumps


    이곳에 .dmp 파일(유저덤프파일)이 생성된다

    반응형
    반응형

    커널 디버깅을 위한 준비물 입니다. 예전에는 Virtual PC 환경에서 윈도우 이미지를 직접 생성해서 사용했습니다만... MS에서 XP 이미지를 제공 하는군요.

     

         * 커널 디버거 : WinDbg

         * 분석용 디버기 : Virtual PC 2007

         * VHD OS 이미지 : Windows XP SP3

     

    1. 디버거(WinDbg) 환경설정

    [File] - [Kernel Debug] 메뉴로 가서 아래와 같이 설정합니다.


     

    2. 디버기(Virtual PC) 부팅 시스템 환경설정

    Virtual PC로 부팅한 시스템 boot.ini 파일의 끝에 아래와 같이 추가 합니다.

     

    [before]

    multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect

     

    [after]
    multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect /debugport=com1 /baudrate=115200 /debug

     

     

    3. 디버기(Virtual PC) 환경설정

    Virtual PC 세팅메뉴에서 COM1 포트를 아래와 같이 설정 합니다.


     

    4. 커널 디버깅 시작

    모든 준비가 끝났습니다. WinDBG를 실행하면 디버기의 신호를 기다리게 됩니다. Virtual PC 부팅 후 WinDBG 창에서 [Debug] - [Break] 를(단축키:Ctrl+Break) 클릭하여 아래와 같은 메시지가 출력된다면 성공 입니다. (WinDBG 커맨드 입력창의 'kd>' 표시는 커널 디버깅 상태를 의미 합니다)


     

    반응형
    반응형
    http://javahawk.egloos.com/10858930

    WinDbg를 이용한 VMWare의 가상머신 Kernel debugging - WinDbg byKircheis

    그러면 이번에는 실제 디버그 정보를 받아볼 WinDbg를 실행해 보자.
    우선 WDK에 포함된 WinDbg를 실행해 보자.
    나같은 경우에는 Debugging Tools for Windows (x64)라는 메뉴에 담긴 것을 실행했다.

    WinDbg를 사용하여 Debuggee와 연결할 때는 비교적 상세한 정보를 받아서 보기를 원할 것이다.
    다음으로 커널 디버깅을 하기 위한 메뉴를 선택한다.
    메뉴에서 Kernel Debug라는 항목을 선택해 준다.

    그러면, Kernel Debugging이라는 창이 나타난다.
    이 창에서는 실제 VMWare에서 맞춰준 Debug 정보 내용을 확인하여 채워주면 된다.
    우선 여기서는 COM2 포트를 가장하여 xcom이라는 pipe를 통해 받기로 이전에 설정했던 설정을 그대로 따라 맞춰준다.
    Serial 통신으로 BR은 115200이었으니 이 또한 동일하게 맞춰준다.
    Serial 통신에서 Baud Rate가 틀어질 경우 전문이 깨져서 나타나는 현상은 다반사이기 때문에 반드시 확인이 필요하다.
    또한 pipe 통신을 사용할 것이기 때문에 Pipe 체크박스를 체크해 준다.
    디버기 환경의 OS가 재부팅될 때 OS 부팅 과정의 디버그 정보까지 확인할 수 있도록 Reconnect를 체크해 준다.
    확인을 눌러준다.

    이제 디버깅 정보를 받을 준비가 모두 끝났다.
    VMWare에서 Debuggee의 환경 정보까지 모두 마쳐졌다면, 이제 해당 OS를 실행시키면 된다.
    디버그 환경에서 OS를 기동하면 역시 평소보다 기동되는 시간이 오래 걸린다.


    일단 Ctrl-Break를 사용해서 디버기와 연결된 상태에서 정보를 잡아 보았다.
    OS를 디버깅할 때는 상세한 정보를 확인할 수 있도록 MS에서 pdb 심볼 파일을 받을 수 있도록 제공해 주고 있다.
    Symbol 파일을 받을 경로를 지정하면 실제 커널 단에서 수행되는 함수의 이름과 변수까지도 확인이 가능하다.
    File - Symbol File Path를 선택하여 나타난 창에 심볼 파일 저장 경로와 MS 사이트를 주소를 포함해서 기록해 주면 된다.
    위의 그림에서는 SRV*D:\DsSymbols*http://msdl.microsoft.com/download/Symbols;D:\DsSymbols 과 같이 설정된 것을 확인할 수 있다.
    물론 이에 대해서는 커맨드 라인에서 명령어를 입력하여 지정 및 확인할 수 있다.
    디버그 창에 나타난 정보들을 유심히 보면 여러가지 정보들을 알 수 있다.
    특별히 *를 사용하여 작성된 창에서는 실행 중 프로세스를 중지시키고 다시 실행시키는 기능에 대한 설명이 포함되어 있다.
    또한, 그 위의 정보를 살펴보면 현재 디버기의 환경의 정보를 몇 가지 확인해 볼 수 있다.
    여기서 밑의 kd>로 표시된 커맨드 라인에 g를 입력하고 Enter를 치거나, F5키를 눌러서 다음 단계를 계속 실행시킬 수 있다.


    커맨드 라인이 *BUSY*로 표시되면서 Debuggee is running...이라고 나타나고 있다.
    이제 필요할 때 마다 Ctrl-Break로 멈춰서 원하는 정보를 확인할 수 있다.
    Visual Studio를 사용하여 디버깅을 해본 사람들이라면 물론 한단계씩 진행하던 F10키를 요구할 수도 있다.
    이것 또한 동일하게 제공되며, 이에 대한 커맨드 라인의 명령어는 p이다.
    다음으로 브레이크 포인트를 잡아보자.


    Break point를 잡기 위한 명령어는 bp이다.
    화면처럼 bp nt!SwapContext라고 입력하면, 커널에서 사용하는 SwapContext 함수의 시작 부분에 bp를 설정할 수 있다.
    물론 화면에 보이는 것과 같이 nt!KeUpdateSystemTime+0x38f 와 같은 포지션도 bp로 설정할 수 있다.
    bp를 설정했다면, 이제 설정한 bp의 전체 리스트를 확인해 보자.
    커맨드 라인에 bl을 입력하여 실행한다.
    화면의 하단에 나타난 정보가 현재 설정된 bp들이다.
    해당하는 소스의 위치와 포지션의 라인넘버까지 확인이 가능하다.
    bp를 설정하면 역시 g를 입력 및 실행하여 해당 포인트에 대한 동작 직전 멈추는 것이 가능해 진다.
    설정된 bp를 지우는 데에 사용되는 명령은 bc이다.

    bc를 입력할 때는 bl로 확인하여 가장 앞에 나타난 인덱스 번호를 확인하여 입력해 준다.
    그리고, 다시 bl을 실행하면 0번 인덱스로 설정되었던 내용이 삭제된 것을 확인할 수 있다.
    WinDbg의 화면 상단에 나타난 Tool bar의 아이콘들을 선택하여 별도의 창을 열어서 확인할 수 있다.
    물론 Alt-Number의 바로 가기 기능을 사용하여 창을 불러올 수도 있다.
    Call Stack - Alt-6


    Disassembly - Alt-7

    Locals - Alt-3


    Memory - Alt-5


    Process and Threads - Alt-9



    Registers - Alt-4


    Watch - Alt-2

    이 창들의 기능은 Visual Studio와 동일하기 때문에 이에 대한 별도의 설명은 생략한다.

    실행 환경에서 자신이 배포한 프로그램에 대한 상세한 디버깅을 원한다면 소스 파일은 아니더라도 pdb 파일은 남겨두는 것이 엉뚱한 문제로 열을 내지 않아도 되는 방법이 될 것이다.

    반응형
    반응형



    참조 : http://silverstr.ufies.org/lotr0/windbg-vmware.html

    커널 영역에서 프로그램을 하다보면 디버깅이 반드시 필요하다.. 

    디바이스 드라이버를 공부하다가 WinDbg라는 디버깅 툴을 알게 되었고  컴퓨터에 세팅을 해보았다.

     전에 선배가 해주었는데 오는 인터넷을 뒤적거리면 하나하나 내 손으로 해 보았다.

    먼저 vmware의 guest os에 시리얼 포트를 만들어 주어야 한다.
    사용자 삽입 이미지
    guest os를 우클릭 해보면 settings를 클릭하면 나오는 화면이다. 여기서 Add를 눌러서 Serial port를 추가 해준다.

    사용자 삽입 이미지

    "Output to named pipe"를 클릭하고

    사용자 삽입 이미지
    각 항목을 위의 그림과 같이 설절해 준다.
    사용자 삽입 이미지
    설정이 다 되면 마지막으로 "I/o mode "에서 Yield cpu poll 를 체크 해준다. 왜그런진 모른다.ㅋ

    이렇게 함으로써 시리얼 포트에 대한 설정이 끝났다.

    다음으로 해야 할 일은 디버기 컴퓨터를 디버깅 모드로 부팅을 시켜주어야 한다.
    boot.ini파일을 수정 하면 된다.
    기본적으로 이 파일을 루트 디렉토리에 있는데 보이지 않게 해두어 있다. 
    폴더 옵션에서 보호된 운영체제 파일 숨기기를 체크 해제 하고 숨긴 파일 보이기를 체크 한다.

    boot.ini파일을 열어서 가장 아래 쪽에 반드시 한줄로 다음의 내용을 추가 해준다.

    multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional - Debug" /fastdetect /debugport=com1 /baudrate=115200

    위의 내용은 윈도우즈 xp에 해당 한다.

    이렇게 함으로써 디버기 컴퓨터에 대한 세팅은 모두 끝났다.

    다음으로 디버거 컴퓨터에 WinDbg를 설치해보고 세팅해보자.

    WinDbg는 마이크로 소프트에서 제공하는 디버거이다. 비주얼 스튜디오에서 컴파일을 해보면
    .pdb라는 파일이 생기는데 이 파일로 디버깅을 하는 것이다. 

    일단, WinDbg를 다운받으려면 ms홈페이지에서 받을 수 있다. 

    다음으로 해야 할 일은 심볼을 설정해주어야 한다. 이 심볼이 .pdb가 있는 곳을 가르쳐 주어야 하는데 지금 디버깅 하려는 대상은 하나의 운영체제 이므로 이 심볼 역시 ms에서 제공하는 것을 다운 받아야 한다. 일단 루트 폴더에 WebSymbols라는 폴더를 만들어 두고, WinDbg를 실행 시켜서 메뉴에 보면 Sysbol file path가 있는데 이 곳에 다음 내용을 넣어 두자
    srv*C:\WebSymbols*http://msdl.microsoft.com/download/symbols 

    다음으로 WinDbg를 실행 시킬때 바로 디버기를 디버깅 할 수 있게 설정하기 위해서 실행 아이콘을 우클릭해서 설정으로 들어가보자
    사용자 삽입 이미지
    "대상"이라는 란에 -k com:pipe,port=\\.\pipe\com_1 이라는 내용을 추가하면 
    모든 것이 끝난다.

    이제 wmware에서 guest os를 실행 시키고 디버거 컴퓨터에서 winDbg를 실행 시키면 연결이 된다...ㅋㅋ

    반응형
    반응형

    http://ethobis.tistory.com/9




    Virtual KD와 Windbg를 이용한 커널 디버깅

    POSTED AT 2010/10/07 19:58 | POSTED IN [#6] PREVIOUS

    가상 시리얼을 통해 Windbg로 커널 디버깅을 할 때에는 속도가 느리고나만 그런지는 모르겠는데가끔 심볼파일 다운로드도 안되고 뭔가 가끔은 시리얼이 제대로 연결되지 않아서 커널 디버깅 시작을 못하는 경우도 여러 번 있었다.

     

    그런데, Virtual KD 라는 디버깅 전용 툴을 사용하면 손쉽게 커널 디버깅을 시작할 수 있다.

     

    다운로드는 아래 링크와 같다.

     

    http://sourceforge.net/projects/virtualkd/files/virtualkd/2.5.1/VirtualKD-2.5.1-sfx.exe/download

     

    다운로드를 받고 압축을 풀면, Vmmon.exe 라는 실행파일이 있다.

    실행하면 다음 화면을 볼 수 있다.


     

    Debugger path를 눌러서 Windbg를 선택해서 설정해 놓으면왼쪽 라디오 박스에 Enable True가 되어 디버깅을 준비할 수 있다.

     

    자동으로 가상 운영체제를 부팅해주는 프로그램을 자동으로 인식해서 목록에 추가한다.

    만약에 Vmware VirtualBox를 실행했다면 다음 그림과 같이 목록에 추가 된다.

     

     

     

    그리고 Run Debugger를 누르면 자동으로 Windbg를 실행해 주는데실행된 Windbg는 연결대기를 계속 기다리고 있다다음에는동일한 폴더에 있는 Target 폴더를 디버깅할 Vmware 윈도우에 복사한다.

     

    그리고 VmInstall을 사용하여 설치한다. 

     

    Target PC에 설치하는 모습이다



    설치되면 자동으로 재 부팅이 되는데재 부팅 되고 나면 밑의 화면이 나온다.

     

     

    이후에 디버그 모드로 진입하면 자동으로 Windbg와 연결된 것을 볼 수 있다.


     

     

    이제 명령어를 칠 수 있고시작할 때, g를 누르면 OllyDbg에서 F9를 누른 효과다. (실행 모드)

     

    그리고 윈도우가 부팅되고 나서 디버그를 계속 진행하고 싶으면 Ctrl + Break를 눌러서 잠시 실행 상태를 멈출 수 있다자세한 방법은 아직 공부를 안 해서 진행을 못하겠다.

    다음 포스팅에……


    반응형
    반응형

    windbg로 블루스크린 MEMORY.DMP 확인하기  프로그래밍

    2012/08/29 10:26

    복사http://blog.naver.com/newwodudrj/30145800892


    1. http://www.microsoft.com/whdc/devtools/debugging/default.mspx windbg 다운로드 후 설치

     

    2. Windows Symbol Packages 다운로드 후 설치

    (checked는 디버그 버전으로 빌드된 윈도우에서 필요하다. 보통의 경우 retail 버전을 받으면 된다)

     

    3. windbg 실행 후 File - Symbol File Path에 다음과 같이 입력

    srv*C:\debugsymbols*http://msdl.microsoft.com/download/symbols

     

    4. File - Open Crash Dump 선택 후 SystemRoot\MEMORY.DMP 열기

     

    5. !analyze -v 입력

    반응형
    반응형


    Windows 7과 Vista에서 덤프파일  Windbg / 밥벌어먹고 살것들 

    2012/01/14 12:52

    복사http://blog.naver.com/backbjw88/40149508692


     덤프파일 이란?

    - 윈도우의 커널 모드에서 문제가 발생하면 화면상에 Crash를 알리는 블루스크린이 뜨면서 해당 시스템 드라이브에 루트(c:\)에 페이지파일에 내용을 쓰게 된다. 이 파일을 재부팅할 때 memory.dmp 파일로 생성하는데 이를 덤프파일이라 부른다

      덤프 파일에는 Crash 당시 메모리 상태를 그대로 저장해 놓기 때문에 포스트모텀 디버깅으로 활용하여 같은 에러가 재차 발생하는 것을 막을 수 있다

     

    최근의 노트북이나 데스크탑의 경우 메모리가 2GB가 넘는 경우가 많아 커널덤프와 미니덤프만 사용하게 되어있으며 미니덤프는 128KB의 크기를 가지며 레지스터, 콜 스택, 프로세스 정보, 스레드 정보, 오류가 발생한 시점에 접근했던 메모리 일부만을 저장한다

     

    실제 커널자체의 에러가 아니라 어플리케이션에 의한 에러일 경우 전체 덤프가 필요할 경우엔 방법이 없을까?

    paging파일의 크기를 메모리의 크기보다 크게 설정하면 된다

     - 고급 시스템 설정의 성능 -> 고급페이지에서 설정 한다

     

    *minidump : c:\windows\minidump, kernel dump, 전체 덤프 : c:\windows\memory.dmp

    (그림 1 - 윈도우 7의 메모리 덤프 설정 페이지 - 제어판 -> 시스템 -> 고급 시스템 설정 -> 시작 및 복구)

     

    윈도우 7에서는 메모리 덤프 생성 조건이 세분화 되었다. 1 -> 4 까지 중첩 if 문이라고 생각하자

    1. 레지스트리 AlwaysKeepMemoryDump 값이 1일 경우 : 무조건 메모리 덤프 생성

    2. Windows 7과 Windows Server 2008 R2 이상 버전 일 경우 :  메모리 덤프 생성

    3. 만약 Windows 7이상의 클라이언트가 도메인에 join 되어 있다면 :  메모리 덤프 생성 

    4. 하드디스크에 25GB 이상의 여유공간이 있을 경우 : 메모리 덤프 생성

     

    * 매번 덮어 씌워지는 커널 덤프와 달리 미니 덤프는 MiniMMDDYY-nn.dmp 형식으로 수 없이 생성 된다. Windows7 에서는 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\CrashControl 의 Minidumpcounts 에서 미니덤프의 최대 갯수를 설정 할 수 있도록 하였다



     


    --------------------------------------------------------------------------------------------------

    윈도우 XP : drwtsn32 명령어를 사용하면 Dr.Watson이라는 덤프파일 생성 프로그램을 관리할 수 잇다

    윈도우 Vista에서는 Dr.Watson을 지원하지 않는다  -> Windbg 참고서에 나온 내용을 그대로 적겠다

     

    1. WinDbg 설치

    2. Regedit.exe 실행

    3. HKEY_LOCAL_MACHINE\Software\Microsoft\windows NT\CurrentVersion\AeDebug를 찾는다

    4. 문자열(REG_SZ) 타입으로 Debugger 키 값을 만든다

    5. Debugger 키 값을 더블클릭하여 다음과 같이 기록한다

      c:\Debugging Tools for Windows\ntsd -p %ld -c ".dump /f /u c:\Temp\mydump.dmp;q"

    6. 문자열(REG_SZ) 타입으로 Auto 키 값을 만든다

    7. Auto 키 값을 더블클릭해 1을 기록한다

    8. Regdit.exe를 닫는다

     

    AeDebug 키를 이용해 응용프로그램에서 오류가 발생했을 때 ntsd를 해당 프로세스에 붙이고(attach) .dump 명령으로 c:\Temp 폴더에 덤프 파일을 생성하게 하는 것이다

     

    -> 다만 윈도우서버 2008, 윈도우 비스타 SP1 이상부터는 자체적으로 덤프파일을 생성하는 기능이 추가 되었다

    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps의 DumpFolder의 다음 레지스트리를 설정하면 작동한다

    Value       / Type             / Default value

    DumpFolder REG_EXPAND_SZ %LOCALAPPDATA%\CrashDumps

    DumpCount REG_DWORD      10

    DumpType   REG_DWORD      1(미니덤프, 2:전체덤프)

     

    발췌 : WinDbg로 쉽게 배우는 Windows Debugging(김성현,이태화,김희준 지음)

    --------------------------------------------------------------------------------------------------

     

     

    반응형
    반응형

    Assert 매크로 커스텀  VC++ Tip 

    2012/03/22 19:45

    복사http://neosafe.blog.me/130134400429


    본 내용은 VisualStudio 2010 기준으로 작성 되었습니다.

     

    어느 C++책을 보더라도 NULL 검사는 꼭 하라고 나옵니다. 

     

    개인적으로는 NULL 검사나 ASSERT를 자주 쓰는 편입니다.

     

    그런데 일반적인 ASSERT함수는 디버깅시에 함수안쪽으로 한단계 더 들어가야하기 때문에 늘 귀찮습니다.

     

    그래서 늘 새 프로젝트를 할때마다 NULL체크 함수와 ASSERT체크 함수를 꼭 만들어서 쓰는데 만들때마다 자꾸 조금씩 까먹어서 이 참에 블로깅을 할까 합니다.

     

    #define _AssertF( _val, _msg)  { if( _val == false) { MessageBox(NULL, _msg, "Assert Message", MB_OK); __asm { int 3 }; } }

    #define _AssertT( _val, _msg) { if( _val == true) { MessageBox(NULL, _msg, "Assert Message", MB_OK); __asm { int 3 }; } }

    #define _Assert( _val, _msg) { { MessageBox(NULL, _msg, "Assert Message", MB_OK); __asm { int 3 }; } }

     

    첫번째 _AssertF는 _val에 해당하는 토큰(taken)이 false일때 _msg에 해당하는 문자열 토큰이 브레이킹(메세지와 함께 일시적 멈춤)과 함께 출력 됩니다.

    두번째 _AssertT는 _val에 해당하는 토큰이 true일때 _msg에 해당하는 문자열 토큰이 브레이킹과 함께 출력 됩니다.

    두개를 구분해 놓은 이유는 기본 ASSERT는 false 중심인데 개인적으로는 이를 맞추기가 좀 헷갈려서 입니다.

    세번째 _Assert는 무조건 _msg에 해당하는 문자열 토큰이 브레이킹과 함께 출력 됩니다.

     

    " __asm { int 3 }"는 어셈블리코드로써 인터렙트를 발생시키라는 뜻입니다.

     

    결국은 아래의 코드처럼 사용하면 됩니다.

     

    //m_bHave가 false일 때 문제가 있음을 감지

    _AssertF( m_bHave, "m_bHave가 false입니다." );

     

    //m_bHave가 false일 때 문제가 있음을 감지

    _AssertF( m_pValue1 == m_pValue2, "같은 값이 들어왔습니다." );

     

    //바로 경고를 띄웁니다.

    if( m_pValue == NULL )

    {

     _Assert("m_pValue가 NULL입니다.");

    }

     

    같이 말한 것으로 NULL체크 함수도 있습니다.

     

    #define _NullCheckRet( _val, _ret, _msg ) { if( _val == 0) { MessageBox(NULL, _msg, "NullCheck Message",MB_OK); __asm { int 3 }; return _ret; } }

    #define _NullCheck( _val,  _msg ) { if( _val == 0) { MessageBox(NULL, _msg, "NullCheck Message",MB_OK); __asm { int 3 }; } }

     

    첫번째 NULL체크 매크로는 _val에 해당하는 값이 0, 즉 NULL이 되었을때 _msg의 문자열에 해당하는 토큰을 출력하며 발동합니다.

    리턴값(_ret)도 삽입할 수 있습니다.

    두번째 NULL체크 매크로는 _val에 해당하는 값이 0이면 무조건 _msg의 문자열에 해당하는 토큰을 출력하며 발동합니다.

     

    _Assert매크로와 _NullCheck매크로와의 차이점은 _Assert는 경고이고 범용적이며 계속 진행이 가능한 코드임에 반해 _NullCheck는 경고이며 포인트를 사용한 변수에게만 한정적으로 쓰고 조건에 해당할때는 그 하단의 코드들은 실행하지 않겠다는 뜻으로 사용합니다.

     

    _NullCheck( m_pSprite, "스프라이트정보가 없습니다." );

    //m_pSprite이 NULL이라면 하단 코드는 실행하지 않고 바로 return 합니다.

    m_nValue = m_pSprite->GetValue();

    m_pSprite->SetIndex(m_nIndex);

     

    bool SetValue( Sprite* _pSprite)

    {

    _NullCheckRet( _pSprite, false, "SetValue을 하는 도중 pSprite가 NULL입니다."

    //_pSprite이 NULL이라면 하단 코드는 실행하지 않고 바로 return false합니다.

    m_nValue = _pSprite->GetValue();

    _pSprite->SetIndex(m_nIndex);

    }

     

    중요한건 매크로 제작시에 최대한 VC의 버젼에 따른 변경사항이 반영되지 않게 했습니다.

    또한 #define 대신에 inline 함수를 사용해도 되지만 그렇게 되면 디버깅시 한스택 더 타고들어가는 불편함을 또 겪어야하기 때문에 의미가 없습니다.

     

    더 추가하자면 __FUNCTION__이나 __LINE__ 같은 것들을 추가할 수 있지만 개인적으로는 복잡하게 정보가 출력되는 것을 그다지 좋아하진 않습니다만 취향에 따라 넣을 수도 있겠습니다.

     

    그리고 "__asm { int 3 }" 대신에 "DebugBreak()"로 대신 할 수 있습니다.

    차이점이라면 어셈블리코드로 짠 브레이킹방법은 해당 스택(함수안)에 중단점을 걸었을 경우 브레이킹이 되지 않는다는 것(VC2010기준)이고 함수를 이용한 방법은 어느때고 브레이킹이 된다는 겁니다.

     

    좀 귀찮긴 하지만(사실 많이 귀찮..) Assert와 Null 검사는 많이하면 많이 할 수록 좋습니다.

    그 결과에 대한 보담은 프로젝트 막마지에 버그 갯수로 말해 줄겁니다.

    반응형

    + Recent posts