반응형



http://blog.naver.com/phoogu/110017552152




" assert의 비법들 "

 

1. assert의 기본

  - assert 매크로 : 코드 상의 어떠한 가정을 철저하게 점검하기 위한 간단하면서도 부담 없는 방법

  - 항상 TRUE가 되어야 하는 조건식을 넣는다. 조건이 FALSE로 평가되면 assert는 문제가 생겼음을 알리는 대화상자를 띄운다.

  - 프로그램을 방어적으로 만들어 준다.

  - 디버그 빌드에서는 수행하지만 릴리즈 빌드에서는 assert 매크로가 컴파일되지 않는다. 그러므로 assert 안에서 프로그램의 상태를 변화시켜서는 안된다.

  #include <assert.h>

  void VectorNormalize( Vec* src, Vec* dst ) {

    assert( src != 0 );

    assert( dst != 0 );

  }

 

2. assert 비법_1) 더 많은 정보를 집어넣는다.

  - assert의 조건식에 더 많은 정보를 집어 넣는다.

  #include <assert.h>

  void VectorNormalize( Vec* src, Vec* dst ) {

    assert( src != 0 && "VectorNormalize::src vector pointer is NULL " );

    assert( dst != 0 && "VectorNormalize::dst vector pointer is NULL " );

  }

 

3. assert 비법_2) 좀더 많은 정보를 집어넣는다.

  - 프로그램의 실행이 도달하지 말아야 할 곳에 도달하는 상황을 감지하기 위해서 assert(0)를 사용하는 경우도 있다. 항상 실패.

  - 부정 연산자 사용

  - assert( !"VectorNormalize:: The code should never get here" );

 

4. assert 비법_3) 좀더 편하게

  - 두 개의 인자들을 받는데, 첫번째 것은 실제로 평가될 조건식이고 두번째 것은 디버깅 정보를 담는 문자열이다.

  - #define Assert(a,b) assert( a && b )

  - Assert( src != 0, "VectorNormalize::src vector pointer is NULL " );

    Assert( 0, "VectorNormalize:: The code should never get here" );

 

5. assert 비법_4) 커스텀 assert 만들기

  - assert보다 더 많은 기능을 가진 독자적인 검사 매크로를 만들 수 있다.

  - 디버거 하에서 조건이 실패ㅏㄹ 경우 소스파일 안의 assert 문이 아니라 assert.c 파일 안에서의 assert 문으로 들어가게 되는 경우 소스파일로 직접 들어가게 만들때 사용된다.

  #if defined(_DEBUG)

    extern bool CustomAssertFunction( bool, char*, int, char* );

  #define Assert( exp, description ) \

    if( CustomAssertFunction( (int)(exp), description, _LINE_, _FILE_) ) \

    { _asm { int 3 } }

  #else

  #define Assert( exp, description )

  #endif

 

6. assert 비법_5) 이것도 중요

  - 커스텀 assert 매크로를 만드는 경우에는 assert 대화상자에 다음부터 항상 무시 옵션을 추가하는 것이 좋다

  - 특정 assert 문에 대해서는 조건이 실패해도 대화상자를 표시하지 않고 무조건 넘어갈 수 있도록 하는 것이다.

  #if defined(_DEBUG)

    extern bool CustomAssertFunction( bool, char*, int, char* );

  #define Assert( exp, description ) \

    { static bool ignoreAlways = false; \

      if( !ignoreAlways ) { \

        if( CustomAssertFunction( (int)(exp), description, _LINE_, _FILE_) ) \

        { _asm { int 3 } }

      } \

    }

  #else

  #define Assert( exp, description )

  #endif

 

7. assert 비법_6) 초고수만 볼 것

  - VectorNormalize를 호출하는 곳이 많다면 VectorNormalize 안의 assert 문은 프로그램을 디버거에 붙여서 실행하지 않는 한 큰 도움이 되지 못한다.

  - assert 대화상자 안에 스택 정보를 표시하면 된다.

 

8. assert 비법_7) 좀 더 쉽게 복사해서 붙여 넣기

  - 스택 정보를 좀 더 쉽게 보존/저장할 수 있는 방법이 필요

  - 윈도우즈 환경에서의 한 가지 해결책은 클립보드를 이용하는 것

  - assert 대화상자에 작은 버튼을 하나 만든 다음 그 버튼을 클릭할 때 스택 정보가 클립보드에 복사되도록 하면 누구라도 쉽게 클립보드의 내용을 버그 리포트나 전자 우편에 붙여 넣어서 프로그래머에게 보낼 수 있다.

  - 임의의 문자열을 클립보드에 복사하는 윈도우즈 전용 코드

  if( OpenClipboard( NULL ) )

  {

    HGLOBAL hMem;

    char szAssert[256];

    char *pMem;

 

    sprintf( szAssert, "Put assert info here" );

    hMem = GloabalAlloc( GHND | GMEM_DDESHARE, strlen( szAssert ) + 1 );

 

    if( hMem)

    {

      pMem = (char*)GlobalLock(hMem);

      strcpy( pMem, szAssert );

      GlobalUnLock( hMem );

      EmptyClipboard();

      SetClipboardData( CF_TEXT, hMem );

    }

   

    CloseClipboard();

  }



반응형
반응형

디버그를 하기위해 assert 함수를 사용하는 경우가 생긴다. 아래는 C 컴파일러에서 지원하는 assert를 사용한 경우이다.

 

assert(pvTo != NULL && pvFrom != NULL);

 

만약 위 assert 함수안의 구문이 참이 아니라면 화면에 에러 메세지를 아래 같이 출력하고 종료할 것이다.

 

Assertion faild: pvTo != NULL && pvFrom != NULL

File pvMemcpy.c line 153

 

하지만 위의 표현식을 포함하는데 있어 문제점은, assert를 사용할 때마다, 조건의 본문 표현을 만들어 낸다는 점이다. 그리고 컴파일러가 문자열을 어디에 보관할 것인가? 보통 컴파일러들은 문자열을 전역 데이터 영역에 보관한다. 그러므로 assert 문자열은 즉시 그 메모리를 잠식해 버린다. 그러므로, 에러 메시지에서 표현식 문자열을 생략하여 출력하는 것이 그 타개책이 될 것이다.

 

#ifdef _DEBUG
void _ASSERT(char *, unsigned int; /* 원형(prototype) */
#define ASSERT(x) \
{ \

    if (x) \
        NULL; \
    else \
    _ASSERT(__FILE__, __LINE__); \
}

 

void _ASSERT(char *file, unsigned int line)

{
    fflush(stdout);
    fprintf(stderr, "\nAssertion failed: %s, line %u\n", file, line);
    fflush(stderr);
    abort();
}

 

assert ASSERT의 주된 차이점은, assert는 표현식(expression)으로써 코드 내에서 자유롭게 사용할 수 있는 반면, ASSERT는 구문(statement)으로써 그 용법이 제한된다는 점이다.

 

파일명, 라인번호 함께 문제가 된 값을 표현한다. 그리고 프로그램을 종료시킨다.

 

ASSERT 함수는 _DEBUG가 정의 되어 있지않으면 아무런 것도 하지 않는 함수이므로 소스를 수정하지 않고도 함수의 에러 처리를 무효화할 수 있는 무척 좋은 함수이다.

반응형
반응형


예외 발생시 콜스택 출력과 미니덤프 생성하기  Visual C++/MFC 

2009/02/09 12:19

복사http://blog.naver.com/harkon/120063141029


디버깅 .NET 어플리케이션책에 포함된, BugSlayer 소스를 vs2005/8 로 재컴파일한것(멀티쓰레드 DLL)


사용법은
압축파일을 받아서, bugslayer 폴드에 압축을 푼다. (예, c:/myproj/bugslayer)
BugslayerUtil/BugslayerUtil.sln 프로젝트 파일을 열어서 release 모드로 컴파일
샘플 테스트 프로그램: bin/release/CrashTest.exe 

라이버러리에 필요한 헤더파일 라이버러리를 복사 (예, c:/myproj/include/bugslayer, c:/myproj/bin/relase)
copy_bugslayer.bat

echo copy bugslayer...
xcopy bugslayer\include\*.h ..\include\bugslayer  /D
xcopy bugslayer\bin\debug\CrashReport.* ..\bin\debug /D
xcopy bugslayer\bin\debug\dbghelp.dll ..\bin\debug /D
xcopy bugslayer\bin\Release\CrashReport.* ..\bin\release /D
xcopy bugslayer\bin\release\dbghelp.dll ..\bin\release /D
pause

적용할 프로젝트에 위 복사한 헤더파일 경로 지정, 라이버러리 경로 지정

c++ 옵션
/I c:/myproj/include/bugslayer

링커 옵션
/LIBPATH:c:/myproj/bin/release

콜스택을 출력할 다이얼로그 생성



WinMain 함수에 크래시 핸들러 설치


#define LOG printf
#define USE_CRASHHANDLER 1
#define TEST_CRASH 0 //테스트요: 강제 널포인트 참조 실행


#if USE_CRASHHANDLER
#include "BugslayerUtil.h"
#endif


HINSTANCE hInst; // 현재 인스턴스입니다.
TCHAR szTitle[MAX_LOADSTRING] = {"MyTest"}; // 제목 표시줄 텍스트입니다.



#if USE_CRASHHANDLER

#pragma comment (lib, "CrashReport.lib")

EXCEPTION_POINTERS *g_pExPtrs;

// 정보 대화 상자의 메시지 처리기입니다.
LRESULT CALLBACK OnCrash(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
LPCTSTR szStr = NULL;
HWND hList = 0;
switch (message)
{
case WM_INITDIALOG:
ShowCursor(TRUE);

LOG("************************************ Crash Occured! ************************************");

szStr = GetFaultReason ( g_pExPtrs ) ;
SetWindowText(GetDlgItem(hDlg, IDC_FAULTREASON), szStr) ;

LOG("FaultRegion: %s", convUni2Mbcs(szStr).c_str());

szStr = GetRegisterString ( g_pExPtrs ) ;
SetWindowText(GetDlgItem(hDlg, IDC_REGISTERS), szStr) ;

LOG("Register:\n%s", convUni2Mbcs(szStr).c_str());

hList = GetDlgItem(hDlg, IDC_CALLSTACK);
szStr = GetFirstStackTraceString ( GSTSO_MODULE     |
GSTSO_SYMBOL    |
GSTSO_SRCLINE    ,
g_pExPtrs        ) ;

while ( NULL != szStr )
{
SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)szStr);
LOG(convUni2Mbcs(szStr).c_str());
szStr = GetNextStackTraceString ( GSTSO_MODULE     |
GSTSO_SYMBOL   |
GSTSO_SRCLINE   ,
g_pExPtrs        ) ;
}

LOG("****************************************************************************************");

EnableWindow(GetDlgItem(hDlg, IDC_MINIDUMP), IsMiniDumpFunctionAvailable ());
return TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
else if (LOWORD(wParam) == IDC_MINIDUMP) 
{
TCHAR dumpFile[100], szTmp[100];
wsprintf(dumpFile, _T("%s.DMP"), szTitle); //APPTITLE _T(".DMP");
BSUMDRET eRet =
CreateCurrentProcessCrashDumpW ( MiniDumpWithHandleData ,
dumpFile,
GetCurrentThreadId ( ) ,
g_pExPtrs              ) ;

ASSERT( eDUMP_SUCCEEDED == eRet ) ;
if ( eDUMP_SUCCEEDED != eRet ) {
wsprintf(szTmp, _T ("MiniDump Save, Failed. Code : %d") , eRet ) ;
} else {
wsprintf(szTmp, _T ("MiniDump Save, Succeed. %s"), dumpFile ) ;
}

MessageBox(NULL, szTmp, _T("MiniDump"), MB_OK);
}
break;
}
return FALSE;
}


LONG __stdcall TheCrashHandlerFunction ( EXCEPTION_POINTERS * pExPtrs )
{
g_pExPtrs = pExPtrs ;

LONG lReturnVal = EXCEPTION_EXECUTE_HANDLER ;

INT_PTR iRet = DialogBox(NULL, (LPCTSTR)IDD_CRASH_DIALOG, NULL, (DLGPROC)OnCrash);

if ( IDOK == iRet )
{
lReturnVal = EXCEPTION_EXECUTE_HANDLER ;
}
else
{
lReturnVal = EXCEPTION_CONTINUE_SEARCH ;
}

g_pExPtrs = NULL;

return ( lReturnVal ) ;
}


void TestCrashAway()
{
char * p = NULL ;
*p = 'p' ;
}

#endif // USE_CRASHHANDLER


int WinMain(LPCTSTR szName, HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    #if USE_CRASHHANDLER
BOOL bRet = SetCrashHandlerFilter ( &TheCrashHandlerFunction ) ;
ASSERT ( TRUE == bRet ) ;

   #if TEST_CRASH
TestCrashAway();
   #endif
  
   #endif

   InitInstance(...)
   CreateWindow(...)
   while (GetMessage(...)) 
   {
    ...
   }

   return 0;
}

기타 

MiniDump 버튼을 누르면, *.DMP 파일이 생성되며, 더블 클릭하면, 비주얼 스튜디오 실행되면서, 클래쉬한 소스의 위치를 가르킨다. 컴파일할때 /Zi 옵션으로, *.pdb 디버깅 심볼파일 생성 필요.

프로세스가 응답없음 상태일때, userdump.exe 를 이용한 미니 덤프 생성하기

압축 파일에 포함된 dbghelp.dll 버전에 따라서, 콜스택을 출력할때, 심볼(함수이름)을 제대로 못읽는 경우가 발생할수 있다. 이 경우, ms 사이트에서 최신버전을 찾아서 설치해 볼것.

Bugslayer 와 비슷한 라이버러리 - 구글 breakpad


적용예

반응형
반응형

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


덤프 파일

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

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

Edition

Visual Basic

C#

F#

C++

Web Developer

Express

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

Pro, Premium 및 Ultimate

항목이 적용됨

항목이 적용됨

항목이 적용되지 않음

항목이 적용됨

항목이 적용됨

이전에는 크래시 덤프라고 했던 덤프 파일을 사용하면 나중에 디버깅하기 위해 프로그램 정보를 저장할 수 있습니다. 덤프 파일은 소스 또는 기호 파일이 없는 컴퓨터에서 프로그램을 테스트할 때 특히 유용합니다. 충돌이 발생할 경우 덤프 파일을 저장했다가 나중에 빌드 컴퓨터나 소스 파일과 디버깅 기호가 있는 다른 컴퓨터에서 덤프 파일을 디버깅할 수 있습니다.


Visual Studio에서 저장하고 여는 덤프 파일은 미니덤프라는 파일 형식을 사용합니다. Visual Studio에서는 힙 정보의 사용 여부와 관계없이 미니덤프 파일을 저장할 수 있습니다.


Visual Studio 2010 디버거는 관리 코드나 네이티브 코드에 대해 미니덤프 파일을 저장할 수 있습니다. 이 디버거는 Visual Studio 2010 또는 파일을 미니덤프 형식으로 저장하는 다른 프로그램에서 생성된 덤프 파일을 로드할 수 있습니다.

여러 가지 방법으로 덤프를 만들고 저장할 수 있습니다.

Visual Studio 2010 디버거에서는 관리 코드, 비관리 코드 또는 이 둘 모두에 대한 정보가 포함된 덤프 파일을 읽을 수 있습니다.일반 디버깅 창을 사용하여 네이티브 덤프와 관리 덤프를 모두 디버깅할 수 있습니다.


다음 단원에서는 덤프를 디버깅하는 방법에 대한 추가 정보를 제공합니다.

개념

기타 리소스





덤프 요구 사항 및 제한

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

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

Edition

Visual Basic

C#

F#

C++

Web Developer

Express

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

Pro, Premium 및 Ultimate

항목이 적용됨

항목이 적용됨

항목이 적용되지 않음

항목이 적용됨

항목이 적용됨

덤프 파일을 디버깅하는 경우 디버깅하는 컴퓨터에서 프로그램의 이진 파일과 PDB 기호 파일에 액세스할 수 있어야 합니다. Visual Studio는 일부 모듈의 누락된 이진 파일을 처리할 수 있지만 유효한 호출 스택을 생성하는 데 충분한 모듈에 대한 이진 파일이 있어야 합니다. 그렇지 않으면 모듈 창에 "일치하는 이진 파일이 없습니다." 메시지가 나타납니다. 자세한 내용은 덤프 모듈 로드을 참조하십시오.


힙을 사용하여 저장된 미니덤프를 로드하는 경우에는 응용 프로그램 이진 파일이 없더라도 Visual Studio에서 기호를 로드할 수 있습니다. 힙이 없는 미니덤프 파일에는 기호를 로드하려면 이진 파일이 필요합니다. 그러나 힙이 없는 미니덤프 파일은 매우 작아 저장소 또는 대역폭 제한이 있는 경우 중요한 고려 사항이 될 수 있습니다. 미니덤프 형식에 대한 자세한 내용은 덤프 파일를 참조하십시오.


Visual Studio 2010에서 디버깅 창을 사용하여 네이티브 및 관리되는 미니덤프 파일을 모두 디버깅할 수 있습니다.

Visual Studio 2008은 디버거 창에 관리 코드 디버깅을 지원하지 않았습니다. SOS라는 도구에 필요한 관리되는 미니덤프 파일을 디버깅하려면 직접 실행 창에서 실행합니다. Visual Studio 2010에서 SOS는 관리되는 미니덤프 파일 디버깅에 더 이상 필요하지 않습니다. SOS를 계속 사용하려면 방법: SOS 사용를 참조하십시오.







Visual Studio 2010에서 네이티브 프로세스나 관리되는 프로세스의 덤프 파일을 향후 디버깅을 위해 저장할 수 있습니다. Visual Studio 또는 기타 덤프 생성 유틸리티에서 만든 덤프 파일을 로드할 수도 있습니다.

덤프 파일을 저장하려면

  1. 디버그 메뉴에서 다른 이름으로 덤프 저장을 클릭합니다.

  2. 다른 이름으로 덤프 저장 대화 상자의 파일 형식 목록에서 미니덤프 또는 힙 사용 미니덤프를 선택합니다.


    힙 사용 미니덤프는 Visual Studio에 사용되는 기본 덤프 형식입니다. 미니덤프는 보다 적은 정보를 제공하지만 그만큼 작은 공간을 필요로 합니다. 자세한 내용은 덤프 요구 사항 및 제한을 참조하십시오.

  3. 탐색 컨트롤을 사용하여 저장 위치를 선택합니다.

  4. 저장을 클릭합니다.


    관리 코드에서 디버깅하는 경우 다른 이름으로 덤프 저장은 관리 코드 미니덤프 파일을 만듭니다. 네이티브 코드에서 디버깅하는 경우 다른 이름으로 덤프 저장은 네이티브 코드 미니덤프 파일을 만듭니다. 혼합형 관리 코드 및 네이티브 모드를 디버깅하는 경우 다른 이름으로 덤프 저장은 관리 코드 미니덤프 파일을 만듭니다.

덤프 파일을 열려면

  1. 파일 메뉴에서 열기를 클릭하고 파일을 클릭합니다.

  2. 파일 열기 대화 상자에서 덤프 파일을 찾아 선택합니다.


    덤프 파일의 확장명은 일반적으로 .dmp입니다.

  3. 확인을 클릭합니다.


    덤프 파일 요약 창이 나타납니다. 이 창에서는 덤프 파일의 디버깅 요약 정보를 보고 기호 경로를 설정하고 디버깅을 시작하고 요약 정보를 클립보드로 복사할 수 있습니다.

  4. 작업 섹션에서 네이티브 전용(으)로 디버그 또는 혼합(으)로 디버그를 클릭하여 디버깅을 시작합니다.


    덤프 파일을 디버깅할 때 이진 데이터를 찾기 위해 Visual Studio 2010에서 기호 검색 경로를 검색합니다. Visual Studio 2010이 이진 파일을 찾을 수 있도록 옵션 대화 상자나 모듈 창에서 기호 검색 경로를 추가할 수 있습니다. 자세한 내용은 방법: 기호 위치 및 로딩 동작 지정을 참조하십시오.







방법: 기호 위치 및 로딩 동작 지정

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

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

Edition

Visual Basic

C#

F#

C++

Web Developer

Express

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

Pro, Premium 및 Ultimate

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

디버거에서 응용 프로그램을 디버깅하기 위해서는 PDB 파일에 저장된 기호 정보가 필요합니다. 기호 정보가 이전 형식인 DBG 파일에 저장된 경우도 있습니다. 디버깅해야 하는 타사 또는 시스템 DLL과 응용 프로그램에 대한 기호 파일이 필요합니다. 기호 파일을 컴퓨터의 디렉터리에 저장하거나 기호 서버에서 다운로드할 수 있습니다.


기본적으로 디버거는 EXE가 있는 위치에서 기호 파일을 로드합니다. 다른 디렉터리나 기호 서버의 기호를 사용하려면 위치를 Visual Studio로 지정해야 합니다.


Visual Studio에서는 디버그 세션을 시작할 때 기호가 자동으로 로드됩니다. Visual Studio에서 기호를 자동으로 로드할 모듈을 지정할 수 있습니다. 모든 모듈에 대해 기호를 자동으로 로드하지 않으려면 모듈 창을 사용하여 추가 기호를 수동으로 로드할 수 있습니다.


기호 서버를 사용하는 방법에 대한 자세한 내용은 방법: 기호 서버 사용을 참조하십시오. 기호 서버를 사용하는 경우 서버가 신뢰할 수 있는지 확인합니다. 그렇지 않으면 보안 위협에 노출될 수 있습니다.

기호 파일이 있는 디렉터리를 지정하려면

  1. 도구 메뉴에서 옵션을 선택합니다.

  2. 옵션 대화 상자에서 디버깅 노드를 열고 기호를 클릭합니다.


    기호 페이지에는 기호 파일(.pdb) 위치라는 상자가 있습니다. 이 상자 위에는 아이콘 네 개가 있습니다.

  3. 폴더 아이콘을 클릭합니다.


    편집 가능한 텍스트가 기호 파일(.pdb) 위치 상자에 나타납니다.

  4. 디렉터리 경로를 입력합니다. 문 완성 기능으로 올바른 형식을 찾을 수 있습니다.


    원격 디버깅을 수행하려는 경우 관리 코드의 기호 파일 및 기호 서버 캐시가 원격 컴퓨터에 있어야 합니다. 네이티브 코드의 기호 파일 및 기호 서버 캐시는 로컬 컴퓨터에 있어야 합니다.

  5. 원격 기호 서버의 기호를 사용하는 경우 기호를 복사할 수 있는 로컬 디렉터리를 지정하면 성능을 향상시킬 수 있습니다. 이렇게 하려면 이 디렉터리의 기호 캐시 상자에 경로를 입력합니다. 원격 컴퓨터에서 프로그램을 디버깅하는 경우 캐시 디렉터리는 원격 컴퓨터에 있는 디렉터리를 가리킵니다.

  6. 확인을 클릭합니다.

기호 경로 목록에서 경로 이름을 제거하려면

  1. 이전 절차의 설명에 따라 옵션 대화 상자를 열고 기호 페이지를 찾습니다.

  2. 기호 파일(.pdb) 위치 상자에서 경로를 선택합니다.

  3. 빨간색 X 아이콘을 클릭합니다.

  4. 확인을 클릭합니다.

자동으로 로드할 기호를 지정하려면

  1. 이전 절차의 설명에 따라 옵션 대화 상자를 열고 기호 페이지를 찾습니다.

  2. 다음에 대한 기호 자동으로 로드에서 제외되지 않은 모두 모듈 또는 지정된 모듈만을 클릭합니다.

  3. 제외되지 않은 모두 모듈을 선택한 경우 제외된 모듈 지정을 클릭할 수 있습니다.


    자동 로드에서 제외할 기호 대화 상자가 나타납니다.


    문서 아이콘을 클릭하여 모듈을 모듈 목록에 추가하거나, 모듈 목록에서 모듈을 선택하고 X 아이콘을 클릭하여 제거합니다.


    끝마쳤으면 확인을 클릭합니다.

  4. 지정된 모듈만을 선택한 경우 모듈 지정을 클릭할 수 있습니다.


    자동으로 로드할 기호 대화 상자가 나타납니다.


    문서 아이콘을 클릭하여 모듈을 모듈 목록에 추가하거나, 모듈 목록에서 모듈을 선택하고 X 아이콘을 클릭하여 제거합니다.


    기본적으로 기호는 응용 프로그램 모듈이 항상 로드되는 디렉터리에 있습니다. 이 기본 동작을 중지하려면 모듈 옆에 있는 기호 항상 로드를 선택 취소합니다.


    끝마쳤으면 확인을 클릭합니다.

  5. 확인을 클릭합니다.

모듈 창에서 수동으로 기호를 로드할 수 있습니다.Visual Basic, Visual C# 또는 Web Developer Express Edition에서는 이 기능을 사용할 수 없습니다.

기호를 수동으로 로드하려면

  1. 모듈 창에서 마우스 오른쪽 단추를 클릭하고 다음에서 기호 로드를 가리킨 다음 기호 경로 또는 Microsoft 기호 서버를 클릭합니다.


    디버거에서 기호 경로 또는 기호 서버를 검색하여 기호를 찾습니다.기호를 찾지 못하면 기호 찾기 대화 상자가 나타납니다.


  2. 기호 찾기 대화 상자에서 로드할 기호 파일을 찾은 다음 확인을 클릭합니다.


    기호 파일은 .pdb 파일 또는 .dbg 파일입니다.

디버그 설정 및 준비




반응형
반응형

http://msdn.microsoft.com/ko-kr/windows/hardware/gg487459




OCA 미니덤프 파일 디버깅

이 페이지에서

온라인 크래시 분석  온라인 크래시 분석
덤프 파일 분석  덤프 파일 분석
심볼을 이용한 실행 코드와 소스 코드 매칭  심볼을 이용한 실행 코드와 소스 코드 매칭
응용 프로그램에 WER 통합  응용 프로그램에 WER 통합


온라인 크래시 분석

온라인 크래시 분석(OCA)은 WER 정보용 보고 장치입니다. 기업에서는 OCA 크래시 덤프를 이용해 고객의 문제를 분석할 수 있습니다.

덤프 파일 분석

덤프 파일은 크래시 발생 시 컴퓨터 또는 프로세스의 상태를 한 눈에 보여줍니다.

개발자가 이 데이터를 분석하려면 사용자 미니덤프 파일을 읽을 수 있는 디버거를 사용해야 합니다. 디버거는 덤프 파일의 콘텐츠와 매칭되는 이미지 및 심볼에도 액세스할 수 있어야 합니다. 대부분의 개발자들은 현재 발생한 크래시를 디버깅할 때 매칭되는 심볼을 사용해야 하는 점은 잘 알고 있습니다. 그러나 미니덤프를 디버깅할 때 디버거에 매칭되는 이미지가 필요하다는 것 역시 간과해서는 안 됩니다.

매칭되는 이미지가 필요한 이유는, 미니덤프 파일이 소량의 정보를 저장하기 때문입니다. 즉, 미니덤프 파일은 크래시 발생 시 휘발성 정보의 일부만을 저장할 뿐, 컴퓨터가 메모리에 로드한 기본 코드 스트림은 저장하지 않습니다. 대신 미니덤프 파일은 공간을 절약하기 위해 크래시가 발생한 컴퓨터에 로드된 이미지의 이름과 타임 스탬프만을 저장합니다.

크래시가 발생한 컴퓨터에서 실행되고 있는 코드를 조사하기 위해, 디버거는 이 컴퓨터가 실행 중인 해당 바이너리에 액세스해야 합니다. 개발자가 크래시를 디버깅하려고 할 때 디버거는 미니덤프 파일에 저장된 이름 및 타임 스탬프를 사용해 바이너리를 고유하게 매칭 및 로드합니다.

이미지 및 심볼이 디버거에 로드되면, 크래시 발생 후 저장된 데이터는 물론 크래시 발생 시의 시스템 상태를 분석할 수 있습니다. 그러나 미니덤프는 해당 문제의 원인이 된 단계를 재현하지 않습니다. 원인을 찾으려면 드라이버의 소스 코드를 분석해 문제의 원인이 된 코드 경로를 찾아야 합니다. 일반적으로 덤프 파일 및 소스 코드를 분석하면 상당수의 문제를 파악하고 해결할 수 있는 것으로 나타나고 있습니다.

심볼을 이용한 실행 코드와 소스 코드 매칭

매칭되는 이미지 및 심볼에 액세스하는 가장 좋은 방법은 Microsoft 심볼 서버를 이용하는 것입니다. 심볼은 디버거가 실행 코드를 소스 코드에 매핑할 수 있도록 해 주는 데이터입니다. 프로그램 구축 시 프로그램의 심볼은 일반적으로 심볼 파일에 저장됩니다. 디버거가 프로그램을 분석하려면 프로그램의 심볼에 액세스해야 합니다.

심볼 파일에는 다음과 같은 정보가 수록됩니다.

  • 모든 기능의 이름 및 주소

  • 모든 데이터 유형, 구조 및 클래스 정의

  • 전역 변수의 이름, 데이터 유형 및 주소

  • 로컬 변수의 이름, 데이터 유형, 주소 및 범위

  • 각 바이너리 지침에 해당하는 소스 코드의 라인 번호

Microsoft Windows 드라이버 개발 키트(DDK)에는 심볼 파일에서 심볼의 수를 줄일 수 있는 도구가 포함되어 있습니다. 소스 수준의 모든 정보를 포함하고 있는 심볼 파일을 풀 심볼 파일이라고 하며, 정보의 양이 줄어든 심볼 파일을 스트립트 심볼 파일이라고 합니다.

심볼 데이터는 Windows 오류 보고(WER) 데이터에서 유용한 크래시 정보를 확보하는 데 매우 중요하기 때문에, 서명할 드라이버를 제출할 때 심볼을 제출하는 것이 좋습니다. 제출된 심볼은 관련 WER 프로세스와 심볼 데이터를 동기화하는 서버에 저장됩니다. 이러한 저장 프로세스를 통해 미니덤프 파일에 보고된 크래시를 쉽게 분류할 수 있으며 결과적으로 Microsoft로부터 더 나은 수준의 데이터를 받을 수 있습니다.

Microsoft는 미니덤프 파일의 Windows 모듈을 분석하는 데 사용할 수 있도록 인터넷을 통해 심볼 서버를 제공합니다. 이 서버에는 Windows 및 기타 몇 가지 제품용 스트립트 심볼 파일이 포함되어 있으며, Windows XP 및 Windows Server 2003용 바이너리도 추가되었습니다. 인터넷의 심볼 서버와 Windows용 디버깅 도구를 이용해 미니덤프 파일을 분석할 수 있습니다.

응용 프로그램에 WER 통합

Windows 오류 보고를 응용 프로그램에 통합할 수도 있습니다. 이 프로세스에는 응용 프로그램 핸들러를 작성하고 ReportFault 기능을 구현하는 작업이 수반되며 보통 하루가 채 걸리지 않습니다.

Windows XP 및 후속 버전의 운영 체제용 응용 프로그램을 작성할 때, Microsoft Windows XP에 새로 추가된 기능을 이용할 수 있습니다. 이 기능은 응용 프로그램의 복구 작동을 보류시키면서 Microsoft에 전송 가능한 표준 오류 보고서를 생성하는 것으로서, ReportFault 라고 합니다. 이 기능을 응용 프로그램 예외 핸들러에서 호출하여 오류 보고서를 생성할 수 있습니다.


ReportFault 기능 참조 자료

페이지 맨 위로 페이지 맨 위로

반응형
반응형

http://www.gpgstudy.com/forum/viewtopic.php?p=49349




"0xㅁㅁㅁㅁㅁㅁㅁㅁ"에 있는 명령이 "0xㅁㅁㅁㅁㅁㅁㅁㅁ"의 메모리를 참조했습니다. 메모리는 "read"될 수 없었습니다. 

프로그램을 마치려면 [확인]을 클릭하십시오. 
프로그램을 디버그하려면 [취소]를 클릭하십시오. 







이미 삭제되거나 해서 쓸수없는 메모리 영역에 접근한거 같은데요 
호출스택 따라가 보시면서 포인터 변수에 쓰레기값 있는지 보세요 
계속 같은 위치에서 뻑나신다면 해당 위치 메모리 주소를 
메모리 창에 적어놓고 값 변하는걸 감시하면서 한줄씩 실행 해보세요 
그리고.. DevPartner 까시면 도움이 될겁니다.






먼저 어떻게 하면 뻗을수 있다를 알아낸다음 
디버그 모드로 실행해서 똑같이하면 뻗을겁니다. 
아니면 계속 디버그 모드로 테스트 하다보면 뻗을겁니다. 
해당지점에 말이죠. 

중요한 말은 0xㅁㅁㅁㅁㅁㅁㅁㅁ의 메모리를 참조했습니다 입니다. 
유효하지 않은 메모리를 찾았다는 것이죠. 
보통 이런 경우는 예전에 잘 사용하던 메모리인데 이제 유효하지 않은 경우이거나 
애초에 초기화 하자 않아서 접근이 안되는 메모리일수도 있죠. 

만약 디버그 모드에서 정말 찾기 힘들다 싶으면 minidump를 사용해보세요. 
배포버전에서 사용하는 방법인데... 
최소한 스택 정보 (호출된 함수, 함수인자값)와 멈춘 코드 정도는 남습니다. 

바로 원인을 알 수 있으면 해결하고 모르겠다면 
로그 남겨 놓고 상황 판단하는 법 입니다. 
디버깅의 기본은 값을 찍어 상황을 판단하는 것이라 생각하면 됩니다.

반응형
반응형

http://cafe.naver.com/jzsdn/17227


#01. 설치방법

그냥 실행파일 클릭해서 설치하면 됨.

 

#02. 경로 설정

VC++ 디렉터리에서 포함 파일과 라이브러리 파일에 VLD가 설치된 경로의 Include폴더와 Lib폴더를 추가시킨다


#03 사용

API면 WinMain() MFC면 App클래스가 있는 cpp파일에 #include "vld.h" 만 맨 위에 넣어주면 됨.

#include "stdafx.h" 가 있다면 그 밑에다가 넣어준다.

메모리가 leak되는 곳이 있으면 출력창에 Call Stack과 Data 파트로 나눠져서 출력이 되는데 Call Stack파트에

자신이 구현한 함수들은 더블 클릭시 그곳으로 이동이 된다.


  

#04. 유의 사항

만약 윈도우즈가 2000이하 라면 dbghelp.dll 파일을 Debug폴더에 복사한다.

 

1. 사용자의 프로그램 경로에 한글이 있을경우 추적경로가 잘려서 제대로 나오지 않은 경우도 있음.
   -> 이럴경우 폴더나 프로그램 이름을 영문으로 수정해야 함.

 

2. static, extern 선언 변수와 같이 프로그램이 종료되기 직전에 메모리를 해제하는 변수는 메모리릭으로 보여지는
    경우도 있다.

   -> vld가 실행되는 시점이 변수 해제 전이기 때문이다. app 파일에 최상위 라인에 적어도 해결이 안될 경우가
       있으므로,
 추적라인의 메모리 해제 부분이 있을 경우 브레이크를 걸어서 프로그램이 종료되고 들어오는 경우
       그냥 넘어가도 될듯하다..;

반응형
반응형

블로그 이미지

3DMP engines

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

by 송정헌





#include <vld.h>  를 써서 헤더선언



download



http://aiesko.blog.me/20139603723

비주얼 스튜디오에서 개발하면서 메모리 누수에 대한 경고는 보기 힘듭니다.

 

그래서 저는 이 플러그인을 이용하여 프로젝트에서 메모리 누수를 확인합니다.

 

첨부한 압축 파일을 압축 해제하면 여러 파일들이 나오는데 간단한 경로에 파일들을 모아놓습니다.

 

그리고 개발하고 있는 프로젝트에서 Alt+F7을 눌러 속성에 들어간 뒤 다음 사진처럼 추가 디렉터리를 설정해줍니다.

 

 

 

변경이 되었다면 진한 글씨로 [설정한 경로];+&~ 해당 옵션(include라면 IncludPath, lib이라면 LibaryPath) 바뀝니다.

 

 

이렇게 되면 준비는 모두 끝났습니다.

 

제가 사용하는 2010은 이렇게 옵션을 적용하면 해당 설정(win32 - 디버그)에만 적용되므로 헷갈리지는 마시구요,

 

사용은 그냥 실행이 아닌 디버그(F5)를 누르시면 됩니다.

 

중단점을 걸지 않으면 프로그램이 실행된 후 바로 꺼질테구 출력 창에 표시가 됩니다.

 

 

이름은 Visual Leak Detector 이구요, 없으면 없다. 있으면 어디에 몇 바이트라고 출력됩니다.

 


 

 

제 출력 창을 복사해보면

 

---------- Block 187 at 0x00218A18: 60 bytes ----------
  Call Stack:
    c:\users\aiko\documents\visual studio 2010\projects\chain\chain\chain.cpp (27): main
  Data:
    58 8D 21 00    A0 8D 21 00    E8 8D 21 00    30 8E 21 00     X.!...!. ..!.0.!.
    78 8E 21 00    C0 8E 21 00    08 8F 21 00    50 8F 21 00     x.!...!. ..!.P.!.
    98 8F 21 00    E0 8F 21 00    28 90 21 00    70 90 21 00     ..!...!. (.!.p.!.
    B8 90 21 00    00 91 21 00    48 91 21 00                    ..!...!. H.!.....

Visual Leak Detector detected 39 memory leaks.
Visual Leak Detector is now exiting.
'Chain.exe': 'C:\Windows\SysWOW64\dbghelp.dll' 언로드
'[444] Chain.exe: 네이티브' 프로그램이 종료되었습니다(코드: 0 (0x0)).

 

187블럭인 메모리 주소 0x00218a18번 주소부터 60바이트까지 메모리 누수가 발생했습니다.

 

소스 위치는 chain.cpp의 메인함수 + 그 메모리 내용

 

39개의 메모리 누수 검출이 감지되었습니다.

 메모리 누수 검출을 종료합니다.

 

누수 검출을 확인해주는 동적 라이브러리 dbghelp.dll을 언로드 하고 프로그램을 종료하는 출력 창 메시지입니다.

 

 

이렇게 해서 어느 정도 누수 문제를 해결할 수 있겠죠?

 

모두 많은 도움이 되시기를 바랍니다!^^





Project Description

Visual Leak Detector is a free, robust, open-source memory leak detection system for Visual C++.

It's pretty easy to use. After installing it, you just need to tell Visual C++ where to find the included header and library file.

Then it can be used with any C/C++ project simply by adding the following line to your code:
#include <vld.h> 

When you run your program under the Visual Studio debugger, Visual Leak Detector will output a memory leak report at the end of your debugging session. The leak report includes the full call stack showing how any leaked memory blocks were allocated. Double-click on a line in the call stack to jump to that file and line in the editor window.

It's a very effective way to quickly diagnose, and fix, memory leaks in C/C++ applications.

The main difference between the CRT Debug Library and VLDis that Visual Leak Detector shows you the complete callstack used for memory allocation has led to the leak.

For example:

---------- Block 1199 at 0x04BE1058: 136 bytes ----------
Call Stack:
d:\Foobar\FooLog.cpp (26): FooLog::getInstance
d:\Foobar\FooMain.cpp (75): FooMain::init
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (578): __tmainCRTStartup
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (403): WinMainCRTStartup
0x759A3677 (File and line number not available): BaseThreadInitThunk
0x770C9D42 (File and line number not available): RtlInitializeExceptionChain
0x770C9D15 (File and line number not available): RtlInitializeExceptionChain
Data:
9C 33 2D 6B    74 2A 2D 6B    C8 11 BE 04    00 00 00 00     .3-kt*-k ........
00 00 00 00    70 14 BB 6C    70 14 BB 6C    00 00 00 00     ....p..l p..l....
00 00 00 00    68 14 BB 6C    68 14 BB 6C    00 00 00 00     ....h..l h..l....
00 00 00 00    6C 14 BB 6C    6C 14 BB 6C    20 12 BE 04     ....l..l l..l....
00 00 00 00    CD 00 CD CD    00 00 00 00    01 CD CD CD     ........ ........
68 14 BB 6C    78 33 2D 6B    00 00 00 00    00 00 00 00     h..lx3-k ........
00 00 00 00    01 02 00 00    06 00 00 00    00 00 00 00     ........ ........
00 00 00 00    00 00 00 00    88 11 BE 04    5C 10 BE 04     ........ ....\...
00 00 00 00    20 CD CD CD                                   ........ ........

This software is provided "AS IS" without warranty of any kind.

The project was originally developed by Dan Moulding, but they are no longer supported. Features of version 2.0 are implemented by Arkadiy Shapkin (me).

Links

Last edited Sep 30 at 7:43 AM by KindDragon, version 18




download

  
  
  
  
 





http://blog.naver.com/jusias?Redirect=Log&logNo=100170133095


MFC의 메모리릭 찾는거에 익숙해져있다가 console에서도 써볼까 했는데 복잡함

vld 받아 include해주면 끝남

 

1. http://vld.codeplex.com/ 에서 vld 받음

 

2. 라이브러리랑 해더파일 위치시킴

C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include 여기라든가 프로젝트 안이라든가

 

3. #include "vld.h"를 프로그램 시작위치에 넣음

 

4. 출력창에 나옴

 

5. 이것저것 설정 바꿈

http://vld.codeplex.com/wikipage?title=Configuration%20Options&referringTitle=Documentation

 

잘씀







반응형
반응형

https://sites.google.com/site/dmoulding/




Visual Leak Detector

A free, robust, open-source memory leak detection system for Visual C++.



Visual Leak Detector


NOTE: This is no longer the official homepage of Visual Leak Detector. The page has moved to vld.codeplex.com.

Visual Leak Detector is a free, robust, open-source memory leak detection system for Visual C++.


Download Version 1.9h (Beta)


It's pretty easy to use. After installing it, you just need to tell Visual C++ where to find the included header and library file.

Then it can be used with any C/C++ project simply by adding the following line to your code:

#include <vld.h>

When you run your program under the Visual Studio debugger, Visual Leak Detector will output a memory leak report at the end of your debugging session. The leak report includes the full call stack showing how any leaked memory blocks were allocated. Double-click on a line in the call stack to jump to that file and line in the editor window.

It's a very effective way to quickly diagnose, and fix, memory leaks in C/C++ applications. 

This software is provided "AS IS" without warranty of any kind.


반응형
반응형

BLOG main image



_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

//일단 이렇게 해놓으면 메모리가 센다는 것만 알수있는게 대부분이고 자세한 중단점을 얻으려면 예상되는 곳에 이것을 작성해야한다


_CrtSetBreakAlloc( 생성 번째 번호 );  //으로 세는 번호를 써서 해당 지점을 잡는다









복사http://blog.naver.com/jungwan82/20080829101




msdn에 보면

 

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

 

위와 같이 정의하고 포함한 후에  프로그램의 종료 지점에서 _CrtDumpMemoryLeaks();  함수를 실행하면 메모리 릭이 발생한 지점을 알려준다고 나와있습니다. 또한 종료지점이 여러군데라서 _CrtDumpMemoryLeaks();를 사용하기가 곤란할 경우에는 프로그램의 시작 지점에 _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); 함수를 실행하는 것으로 대체할 수 있다고 합니다.

 

그런데 종료지점에도 _CrtDumpMemoryLeaks() 함수를 실행하고 시작지점에도 _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ) 함수를 실행하면 어떻게 될까요?

 

발생하지도 않은 메모리 릭을 보고합니다. 사람 고생시키는 경우입니다.

반응형
반응형

http://blog.naver.com/kienuu/10015143165


분류: Win32/MFC
이름: 박상백(출처 : http://www.yunubeback.com/bbs/zboard.php?id=DevBoard)

http://www.yunubeback.com/bbs/data/DevBoard/Funny_Memory_Values.mht
http://www.yunubeback.com/bbs/data/DevBoard/Memory_Debug_Codes.mht



디버깅중이나 에러 발생시 마주치는 이상하기도 하고 우습기도 한 메모리주소가 있습니다.
이러한 메모리주는 일정하게 특수한 값으로 설정되곤 하는데 그 값들은 각각 의미를 가지고 있습니다.

Microsoft Visual C++ Runtime Library (DEBUG_NEW가 선언된 상태)
(1) 0XCD, 0xCDCD, 0xCDCDCDCD
   - malloc() 또는 new로 객체가 생성되고 아직 Write한 적이 없는 상태
(2) 0xFD, 0xFDFD, 0xFDFDFDFD
   - "No man's land"
   - 요청한 블럭에 속하지 않는 위치에 존재하는 몇Bytes가량의 금지구역
   - 메모리 경계검사를 위해 삽입됨
(3) 0xDD, 0xDDDD, 0xDDDDDDDD
   - free() 또는 delete로 객체를 Free한 상태

Compiler Initialization
(1) 0xCC, 0xCCCC, 0xCCCCCCCC
   - VC++에서 /GZ옵션을 넣어 컴파일하는 경우에만 적용됨
   - 초기화되지 않은 변수들은 모두 이러한 형태의 값을 갖게 됨

Windows NT Memory Codes
(1) 0xABABABAB
   - LocalAlloc()함수에 의해 할당된 메모리 블럭
(2) 0xBAADF00D
   - "Bad Food"
   - LocalAlloc(LMEM_FIXED, ...)를 통해 할당된 메모리 블럭이지만 아직 Write한 적이 없는 상태
(3) 0xFEEEFEEE
   - HeapAlloc() 또는 LocalAlloc()함수에 의해 할당될 예정인 메모리
   - HeapFree()함수를 통해 이미 Free된 상태

* 자세한 내용은 첨부파일 참조

 

 

물론 아래 구문으로 전부 예외 처리가 가능하기야 하지만서도 ..ㅎㅎ

try{

}

catch(...)

{

}

반응형
반응형

출처블로그>그래 자네 꿈은 먼가? | 

원문http://blog.naver.com/edun81/50003974011

 Visual Studio 에서 개발할 경우 메모리 누수를 확인할려면

디버그 모드에서 F5 (Ctrl+F5 아님로 프로그램을 실행하면 되는건 아시죠?

이때 C++ 의 경우는 new 를 사용하고 메모리 반환을 하지 않는경우 해당 위치를 output 창에 보여줍니다.

예를 들어 아래의 코드로 메모리 할당후 어디에서도 반환하지 않았다고 가정해봅시다.

             char *pszTest = new char[100] ;

F5 로 프로그램 실행후 종료하면 Debug 출력창에 아래와 같이 나옵니다.

Detected memory leaks!

Dumping objects ->

D:\\Project\\MemoryTest.cpp(60) : {73} normal block at 0x00374E58, 100 bytes long.

 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD

Object dump complete.

 

F4 또는 위의 파일경로명을 더블클릭 하면 해당 위치 소스코드의 포커스를 이동해주기 때문에

메모리누수를 해결하는데 아주 편리합니다.

이렇게 가능한 이유는 비쥬얼스튜디오에서 프로젝트 생성시 자동으로 추가된 아래의 구문 때문입니다

 

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

보시면 아시겠지만 new 라는 놈을 DEBUG_NEW 로 다시 정의하였습니다.

실제 디버그에선  new 를 사용해도, DEBUG_NEW 가 실행하게 되는것입니다.

그렇다면 DEBUG_NEW 의 정체가 뭘까요?

 

DEBUG_NEW 가 정의되어있는 소스코드를 가보겠습니다.

DEBUG_NEW 는 <AFX.H> 에 정의되어 있고내용은 아래와 같습니다.

#define DEBUG_NEW new(THIS_FILE, __LINE__)

오호라~ new 가 연산자 오버로딩 되어 있는게 확인됩니다.

일반적으로 우리가 생각하는 new 는 인자로 할당할 크기만 주게 되어 있습니다.

하지만위의 구문을 보면 해당 위치의 파일명과 라인수를 지정하게 되어 있군요.

다시말해, new 를 사용할때마다 사용된 곳의 파일 경로와 해당 라인수를 메모리에 함께 등록하는 것입니다.

 

결국 해당 메모리가 제거되지 않았을땐메모리에 기록해둔 파일경로와 라인수를 참조해서 디버그 출력창에 뿌려주고

이를 식별자로 사용하여 이동하기 쉽게 해주고 있습니다.

여기까지는 비쥬얼 스튜디오가 자동으로 해주기 때문에 크게 신경쓸 일이 없었습니다.

하지만문제는 코드일 경우입니다.

비쥬얼스튜디오는 불행하게도 코드로 된 프로젝트를 생성하는 마법사가 없습니다.

그러다보니 자동으로 생성해주는 메모리 누수 매크로도 제공하질 않습니다.

실제 코드에서 사용하는 malloc 을 사용해서 메모리 해제 하지 않고 결과를 보겠습니다.

char *pszTest2 = (char*)malloc(100*sizeof(char)) ;

위코드를 수행후 종료하면 디버그출력창에 아래와 같이 나옵니다.

etected memory leaks!

Dumping objects ->

{73} normal block at 0x00374E58, 100 bytes long.

 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD

Object dump complete.

도대체 어떻게 하라는건지

더블클릭해도 아무 반응도 없고어디서 메모리 해제가 일어났는지 아무런 정보도 주질 못하고 있습니다.

 

그렇다고 포기할순 없죠.

C++ 의 new에 사용했던 방식대로 의 malloc 에도 똑같이 해주면 될 것 같습니다.

malloc 할때 현재 파일경로와 라인수를 식별자로 함께 등록해주면 되겠군요.

그렇다면 이러한 매크로(DEBUG_NEW와 같은)를 직접 만들어야 할까요?

 

친절하게도 비쥬얼스튜디오 헤더파일에 미리 다 만들어 놨더군요.

우선 결과 코드를 보겠습니다.

#ifdef _DEBUG

#include <crtdbg.h>

#ifdef malloc

#undef malloc

#endif

#define malloc(s) (_malloc_dbgs_NORMAL_BLOCK, __FILE__, __LINE__ ))

#endif

 

new 를 사용할 때 처럼, malloc 을 다시 다른 함수를 사용하게 정의하였습니다.

위 코드를 소스코드의 상단에 위치시킵니다.

그런후 다시 아까의 코드를 수행후 종료하면 친절한 디버그 출력창으로 바뀐걸 볼 수 있습니다.

Detected memory leaks!

Dumping objects ->

D:\\Project\\MemoryTest.c (68) : {73} normal block at 0x00374E58, 100 bytes long.

 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD

Object dump complete.

 

위 매크로를 보시면 _malloc_dgb 라는 매크로가 보입니다.

우린 그저 가져다 쓴것에 불과하군요.

<crtdbg.h> 를 열어보시면 메모리 관련 함수인  malloc, calloc, realloc, expand, free, msize 에 대한

디버그용 매크로가 정의되어 있는걸 보실 수 있습니다.

그렇다면 _malloc_dgb 에서 사용된 인자들의 의미가 과연 무얼까요?

는 실제 할당할 크기(사이즈입니다.

_NORMAL_BLOCK 는 시스템에서 메모리를 할당할 때 사용되는 블록의 기본 단위 크기 입니다.

 __FILE__ 은 현재 코드의 전체 경로명입니다.

__LINE__ 은 현재 코드의 수행중인 라인수 입니다.

다시,  crtdbg.h 를 보시면 free 라는 놈도 디버그용이 있습니다.

이왕 하는거 위에서 정의된 모든 메모리 관련 함수에 대해서 디버그용으로 변경해 봅시다.

#ifdef _DEBUG

#include <crtdbg.h>

           #ifdef malloc

           #undef malloc

           #endif

           #define malloc(s) (_malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__ ))

           #ifdef calloc

           #undef calloc

           #endif

           #define calloc(cs) (_calloc_dbg(cs, _NORMAL_BLOCK, __FILE__, __LINE__ ))

           #ifdef realloc

           #undef realloc

           #endif

           #define realloc(ps) (_realloc_dbg(ps, _NORMAL_BLOCK, __FILE__, __LINE__ ))

           #ifdef _expand

           #undef _expand

           #endif

           #define _expand(ps) (_expand_dbg(ps, _NORMAL_BLOCK, __FILE__, __LINE__  ))

           #ifdef free

           #undef free

           #endif

           #define free(p) (_free_dbg(p, _NORMAL_BLOCK))

           #ifdef _msize

           #undef _msize

           #endif

           #define _msize(p) (_msize_dbg(p, _NORMAL_BLOCK))

#endif

 

반응형
반응형

블로그 이미지

3DMP engines

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

by 송정헌





1.초기화되지 않은 변수를 사용


2.쓰래기값 포인터를 참조하는 경우

  :  잘못 참조할 경우 디버깅으로 call stack 을 보면 0xC0000005 번지를 가르킬때가 발생하게됨

반응형
반응형

http://loger1000.springnote.com/pages/1715936



헤더파일: <crtdbg.h>

 

_CrtDumpMemoryLeaks() : 이 함수는 함수 호출 시점 전까지 발생한 메모리 릭 정보를 출력한다

* 디버그 모드에서만 사용한다.

 

_CrtSetDbgFlag() : 이 함수는 메모리릭 발생 된 이후 시점에서 호출한다.

 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

프로그램 시작부분에 아래와 같이 함수를 호출하여 사용한다.

_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

 

_CRTDBG_ALLOC_MEM_DF  플래그 값이 디버그모드에서 메모리 할당이 일어날 때 마다 추적한다.

_CRTDBG_LEAK_CHECK_DF 플래그 값이 프로그램이 종료되기 전에 자동으로 _CrtDumpMemoryLeaks() 함수를 호출하여 메모리를 할당한 후 해제 하지 않는 메모리가 있는지 확인한다.

 

// 예제 코드
#include <stdlib.h>  // malloc 함수 사용
#include <crtdbg.h>

 

void main()
{
  _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

  char* cp;
  cp = (char*)malloc(16);
}

 

위와 같이 하면 malloc(16) 에 대해서 메모리 릭을 경고한다. (할당 후 해제 하지 않았으므로)







http://cafe.naver.com/ddugi/22



뚜기아빠(introc)

카페매니저

http://cafe.naver.com/ddugi/22  

http://dasomnetwork.com/~leedw/mywiki/moin.cgi/CRT_c0_c7_20_b5_f0_b9_f6_b1_d7_20_b1_e2_b4_c9_c0_b8_b7_ce_20_b8_de_b8_f0_b8_ae_20_b4_a9_bc_f6_20_b5_f0_b9_f6_b1_eb_c7_cf_b1_e2?action=highlight&value=VisualC%2B%2B%C6%C1%C1%F6%B5%B5

 


 

Written by gazette2 (gazette2@ttl.co.kr) 

일반적으로 가장 잡기 힘든 버그의 하나로서 메모리 누수, 메모리 Overwrite등을 꼽을 수 있다. 이런 문제점을 해결하기 위해 CRT(C Runtime library)에서는 여러가지 다양한 메모리 관련 디버그 함수들을 제공한다. 그러나 이것들이 디폴트로 사용하기 힘들게 꺼져 있기 때문에 대부분의 프로그래머들은 이 사실을 알지 못하는 경우가 많다. 그래서 이 글에서는 CRT의 디버그 관련 함수들에 대해 알아보고 어떻게 사용하는 것이 좋은지에 대해 논해 보려고 한다. 

John Robbins(필자가 가장 좋아하는 프로그래머 중의 한명)가 지은 Debugging Applications 이라는 책에도 좋은 내용들이 있으니 참고하기 바란다. 그러나 여기 나온 팁은 그 책에는 나와 있지 않은 것이다. Numega Bounds Checker나 Rational Purify등의 툴이 비싸서 엄두도 못내는 분들께는 좋은 내용이 되리라 믿는다 

메모리 누수 

개요 

CRT가 출력해 주는 메모리 누수 리포트 결과를 간혹 본적이 있는 사람도 있을 것이다. 만약 MFC를 주로 사용한다면 이와 같은 메시지를 자주 볼 수 있다. 왜냐하면 MFC에서는 기본적으로 CRT 디버그 기능을 켜기 때문이다. 메시지 내용은 다음과 같다 

Dumping objects -> 

 

{65} normal block at 0x003748B0, 48 bytes long. 

 

 Data: <@H7 @H7 @H7     > 40 48 37 00 40 48 37 00 40 48 37 00 CD CD CD CD  

 

{64} normal block at 0x00374840, 48 bytes long. 

 

 Data: < H7  H7  H7     > B0 48 37 00 B0 48 37 00 B0 48 37 00 CD CD CD CD  

 

Object dump complete. 

이 메시지의 내용은 두개의 블록이 할당된다음 해제되지 않았다는 것을 의미한다. 그렇다면 우선 이 메시지들에 대해 대략 알아보도록 하자 

우선 {64}, {65}와 같은 것은 메모리에 할당된 순서로서, 각각 64번째, 65번째 할당된 메모리가 해제되지 않았음을 나타낸다. Normal block이라 함은 사용자에 의해 일반적인 new, delete, malloc등으로 할당된 메모리라는 뜻이다. 그리고 그 메모리 포인터 주소를 알려주고 있으며, 몇 바이트짜리 메모리 블록인지도 나와 있다 

Data:… 라인은 그 메모리의 선두번지로부터 실제 메모리의 내용이 어떤 값을 포함하고 있는지를 나타내는 것이다

그러나 위의 메시지를 보았듯이 실제로는 아무 도움이 되지 않는다는 것을 금방 알수 있을것이다. 왜냐하면 메시지의 내용이 너무 암호와같이 복잡하다는데 문제가 있다. 몇줄짜리 프로그램이라면 또 모르겠으나, 거대한 프로그램인 경우 실제로 64,65번째 할당된 메모리를 순서대로 추적하는 것은 너무나도 어려우며, 어떤 포인터에 어느 번지의 메모리가 할당되었는지를 확인하는 것도 불가능에 가깝다고 할 수 있다. 또 자신이 만든 클래스나 구조체가 몇 바이트짜리인지를 일일이 확인한다는 것도 불가능하다. 

그렇다면, 이 문제를 어떻게 해결해야 할 것인가? 실제로 CRT에는 여러가지 도우미 함수들을 포함하고 있어서 이 문제를 좀 더 쉽게 해결할 수 있도록 해 준다. 그러나 제대로 알고 사용하지 않는다면 결국에는 또다른 암호 코드만을 추가로 더 얻게 될 뿐이라는 것도 알아야 한다 

샘플코드 

#include "stdafx.h" 

 

int main() 

       int *p = new int; 

 

       return 0; 

 

위의 코드는 int *를 할당하고 해제하지 않았으므로 명백한 메모리 누수이다. 그러나 이 프로그램을 빌드하고 디버그해봐도 프로그램 종료시 아무런 메시지를 남기지 않는다. 즉 메모리가 샌것인지, 혹은 Overwrite가 일어났는지 등을 확인할 길이 전혀 없다. 그러면 프로그램 일부를 수정해 보도록 한다 

#include "stdafx.h" 

#include <crtdbg.h> 

 

int main() 

 

       int *p = new int; 

 

       _CrtMemDumpAllObjectsSince(0); 

 

       return 0; 

_CrtMemBumpAllObjectsSince를 사용하기 위해 crtdbg.h를 인클루드 하고, 프로그램 종료 직전에 함수를 호출했다 디버그를 시작하고 프로그램을 종료하면 출력결과는 다음과 같다

Dumping objects -> 

 

{64} normal block at 0x00374838, 4 bytes long. 

 

 Data: <    > CD CD CD CD  

 

Object dump complete. 

The thread 0x65C has exited with code 0 (0x0). 

The program 'test.exe' has exited with code 0 (0x0). 

위에서 설명한것과 비슷한 종류의 메시지가 포함되어 있는 것을 알 수 있을 것이다. 이 메모리는 64번째 할당된 일반 메모리이며 0x00374838번지에 4바이트 할당되었음을 알 수 있다. 또 데이터 내용은 16진수로 CD CD CD CD이다 이 정보만으로도 많은 것을 알 수 있다. 예를들어 데이터가 CD CD CD CD라는 것은 할당만 해놓고 전혀 초기화를 하지 않았다는 의미이다. 단순한 위의 프로그램 만으로도 사용자가 처음 할당한 메모리가 64번째만에 할당되었다. 이유가 무엇일까? 이유는 간단하다. main함수가 호출되기 이전에 이미 많은 메모리 할당 요청이 있었고, 그것은 프로그램을 실행시키기 위해 운영체제나, CRT가 이미 사용했기 때문이다. 위의 프로그램은 단순하기 때문에 어디서 메모리가 샜는지 한눈에 척 알 수 있다. 그러나 메모리를 수십~수백번씩 할당했다 해제하는 일반 애플리케이션에서는 어떻게 정확히 64번째 할당된 메모리를 찾아낼 수 있을까? CRT에서 내준 정보는 CRT를 이용해 분석 가능하다 main함수가 처음 시작되기 전에 다음의 함수를 사용하도록 하자 

… 

       _CrtSetBreakAlloc(64); 

 

       int *p = new int; 

… 

이 함수는 64번째 메모리 할당이 발생할 경우 프로그램 실행을 중지하고 디버거로 제어를 넘기라는 의미이다. 실제로 프로그램을 실행시켜 보면, “crtdbg.exe의 0x00411cb7에 처리되지 않은 예외가 있습니다. 사용자 중단점”과 같은 메시지를 출력하면서 프로그램 실행을 중지하게 된다. 브레이크 포인트가 가리키는 위치는 CRT의 메모리 할당 함수 내부이며, Call Stack을 따라가 보면 어느곳에서 할당이 일어났는지 바로 알수 있게된다. 

전역 변수와 CRT 디버깅 

다음과 같은 프로그램을 보도록 하자 

#include "stdafx.h" 

#include "crtdbg.h" 

#include <crtdbg.h> 

 

class A 

public: 

       A() { p = new int; } 

 

private: 

       int *p; 

}; 

 

A a; 

 

int APIENTRY _tWinMain(HINSTANCE hInstance, 

                     HINSTANCE hPrevInstance, 

                     LPTSTR    lpCmdLine, 

                     int       nCmdShow) 

       _CrtSetBreakAlloc(64); 

 

       _CrtMemDumpAllObjectsSince(0); 

 

       return 0; 

이 프로그램을 디버그 해 보면 똑 같은 메모리 누수를 보고하긴 하지만, 그러나 64번째 메모리 할당에서 정지하지 않는다. 이유가 무엇일까? 

이유는 간단하다. A라는 클래스의 인스턴스인 a가 전역변수로 선언되었기 때문에 main함수가 호출되기 이전에 생성되기 때문이라는 것이다. a가 이미 생성되고 난 다음에 브레이크 포인트를 설정하니, 브레이크 포인트가 먹힐리가 없다. 그럼 방법이 없는 것일까? 

답은 간단하다. 모든 할당이 일어나기 직전에 프로그램을 정지시켜놓고, 64번째 메모리 할당이 일어날 때 브레이크 하라는 명령을 주면 된다. 그럼 어떻게 하면 될까? 다음과 같이 하도록 한다. 

CRT소스에서 WinMainCRTStartup()함수를 찾아낸다. 이 함수는 실질적인 main함수이며, 프로그램이 로드되기 전에 가장먼저 실행된다. 이 함수 내부에서 여러분이 정의한 main 또는 WinMain함수를 호출하게 된다. 이 함수는 파일의 찾기 기능을 이용하거나, 또는 crt0.c파일을 바로 열어서 찾아도 된다. 그러나 더 간단한 방법은 main함수에 BP를 찍어놓고, 한번 실행시킨다음 call stack을 거슬러 올라가는 방법이다. 

WinMinCRTStartup함수의 시작부분에 BP를 찍어놓고 다시 디버거를 시작시킨다 

Watch창을 열어 _crtBreakAlloc 변수를 확인해 본다. 아마 -1일 것이다. 

이 변수값을 원하는 메모리 할당 번지(위의 경우64)로 바꾼다. 

다시 실행시키면 64번째 메모리 할당을 하기 전에 정지한다. 

이 기술은 코드를 재 컴파일 하지 않아도 디버거 상에서 바로 브레이크 포인트를 수정할 수 있다는 장점이 있다. 현재 이 방법 보다 간단하게 할 수 있는 방법은 현재 연구중에 있다. 좋은 결과가 나오는대로 다시 여러분들에게 알려드리도록 하겠다. 

이상 몇가지 메모리 누수를 찾아내는 방법을 살펴보았다. 그러나 주의할 것은 반드시 crtdbg.h를 같이 인클루드 해야 한다는 것이며 _DEBUG매크로가 정의되어 있을때에만 제대로 동작한다는 것이다. 

CRT Debug 기능 사용법 2 

요즘 CRT의 디버그 기능을 연구하기 시작하면서, 그동안 정말 좋은 기능들을 여럿 묵혀놓았다는 느낌을 지울수가 없습니다. 어렵게 메모리 관련 디버깅 루틴을 만들지 않아도, 너무나도 정확히 메모리 관련 에러를 잡아주니 STL을 처음 쓸 때 만큼이나 편리하게 느껴지더군요. 그럼 그동안 제가 연구한 것에 대해 보고드리도록 하겠습니다 

지난 내용의 메모리 누수가 아닌 것 까지 모두 보고하는 문제 

지난번 예제에서 약간만 더 수정해 보자 

#include "stdafx.h" 

#include <crtdbg.h> 

#include <list> 

using std::list; 

 

typedef list<int> IntList; 

typedef IntList::iterator IntListIter; 

 

IntList myList; 

 

int main() 

       _CrtMemDumpAllObjectsSince(0); 

 

       return 0; 

 

위의 프로그램은 메모리 누수를 한 개 보고한다. 위치는 myList의 생성자이다. 그러나 정말 그것이 샌것일까? 그렇다면 STL은 항상 메모리 누수가 있다는 말인가.. 이것저것 고민하던 중에, 진짜 Main함수는 {{{WinMainCRTStartup()}}}라는 사실이 생각났고, 디버그 상에서 {{{WinMainCRTStartup()}}} 메소드의 끝까지 따라가 보았다. 그랬더니 다음과 같은 루틴을 찾을 수 있었다. (처음에는 숨겨진 함수를 찾았다고 생각했으나, 알고봤더니 MSDN에 이미 문서화 되어있는 함수였다. 역시 소스보다는 문서를 찾아보는 것이 우선이다 -.-) 

{{{

/* Dump all memory leaks */ 

if (!fExit && _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) & _CRTDBG_LEAK_CHECK_DF) 

    fExit = 1; 

    _CrtDumpMemoryLeaks(); 

_CrtSetDbgFlag이라는 함수는 CRT디버거의 전역 플랙을 셋팅하는 함수이다. 위에서 보다 시피 이미 CRT의 메인함수가 종료할 때 메모리 누수를 검사하고 있었던 것이다. 다만 디폴트로 꺼져 있었으며 열쇠는 _CrtSetDbgFlag이라는 함수가 쥐고 있다. MSDN에서 찾아본 결과 다음과 같다.

_CrtSetDbgFlag함수는 다섯개의 Flag이 있다.

_CRTDBG_ALLOC_MEM_DF : 디폴트로 켜져 있으며, 디버그 버전에서 모든 메모리 할당이 일어날 때마다 추적 가능하도록 특별한 기능을 추가해 둔다. 이 플랙이 켜져 있어야 메모리 누수를 안전하게 검사 할 수 있다. 

_CRTDBG_DELAY_FREE_MEM_DF : delete, free등으로 삭제되어도 바로 삭제되지 않고, CRT의 메모리 관리소에 남아 있다가 프로그램 종료시에 완전히 삭제된다. 

_CRTDBG_CHECK_ALWAYS_DF : 모든 메모리관련 연산에서 _CrtCheckMemory를 호출한다. 이 메소드는 이후에 다시 살펴볼 것임 

_CRTDBG_CHECK_CRT_DF : CRT가 내부적으로 할당한 블록도 메모리를 체크할 때 포함한다. 일반적으로는 CRT가 할당한 블록은 메모리 체크에서 제외된다. 일반적으로 사용하지 않는다 

_CRTDBG_LEAK_CHECK_DF : 프로그램이 완전히 종료되기 직전에 아직 해제되지 않은 메모리가 있는지 검사한다. 프로그램의 종료 포인트가 여러군데 있는 경우에 사용하면 일일이 _CrtDumpMemoryLeaks 메소드를 호출하지 않아도 자동적으로 메모리 누수를 검사할 수 있게된다. 

이 중에서 첫번째 플랙만을 제외하고는 모두 디폴트로 꺼져있다. 그러므로 다음과 같이 메모리 검사 기능을 켜도록 한다 

_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 

위의 프로그램에서는 다음을 삭제한다 

_CrtMemDumpAllObjectsSince(0);  

_CrtMemDumpAllObjectsSince 함수는 실제로는 특정 지점에서 지점간에 할당되어 있는 메모리들을 보고해 주는 함수이다. 인자로 0을 넘겨주면 처음부터 지금까지 할당되어 있는 메모리들을 보고해 준다. CRT가 아직 전역으로 할당된 메모리를 완전히 삭제하기도 전에 호출했기 때문에 STL의 메모리가 샌 것 처럼 보인것이다.

CRT 메모리 블럭 

다음으로 넘어가기 전에 다음을 짚어보고 넘어가기로 하자. 디버그 버전에서는 메모리가 할당되거나 사용되기 직전에 특정한 값들로 할당된 메모리가 채워진다는 것을 알고 계실것이다. 의미는 다음과 같다 

0xFD : 메모리 블록 양 끝의 버퍼에 생성된다 

0xCD : 새로 생성된 버퍼에 저장되는 기본값이다 

0xCC : 스택에 변수가 생성되면 우선 이값으로 채워진다 

0xDD : 삭제된 메모리 블록은 이 값으로 채워진다 

다음 예제를 보자 

int main() 

{    // 함수 시작지점 

 

       _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 

 

       int *p = new int [10]; // 메모리가 할당되는 지점 

       printf("%d", *p); 

       delete [] p;  // 메모리가 삭제되는 지점 

 

       return 0; 

함수 시작지점에서 포인터 p는 초기값으로 0xCCCCCCCC를 갖게 된다. 디스어셈블 해보면 모든 지역변수들을 0xCC로 채워넣는 것을 볼 수 있다. 이후 메모리가 할당되는 지점에서 아마도 sizeof(int) * 10 바이트의 메모리가 할당될것이다. Sizeof(int)가 4바이트라면(32비트 운영체제에서) 40바이트가 생성되는 것이다.(디버그 버전이라는 가정하에) 이렇게 생성된 40바이트에 0xCD값이 채워진다. 만약 어떤 포인터의 값을 읽었을 때 값이 0xCDCDCDCD와 같은 형식이거든 초기화안된 메모리를 읽었다고 생각하면 된다. 

그런데, 위의 할당지점에서 실은 48바이트가 생성된다. 40바이트 할당 명령을 주었는데 왜 48바이트의 메모리가 할당되었는가 이유는 위의 0xFD값에 있다. 40바이트의 블록을 생성시키고 그 블록의 앞과 뒤에 각각 0xFDFDFDFD를 삽입시켰기 때문이다. 이 값이 채워지는 이유는 다음과 같이 접근하는 경우 

p[-1] = 10; // underwrite 

p[11] = 10; // overwrite 

0xFD로 채워진 메모리의 일부분이 깨질 것이고, 나중에 사용할 메모리 체크 명령에 의해 overwrite/underwrite가 발생했다는 사실을 알 수 있게된다. 

마지막으로 메모리가 삭제되는 지점에서는 이론 대로라면 p값이 0xDD로 채워질 것이다. 그러나 실제로 필자의 컴퓨터에서는 0xFEEE가 채워졌다. 왜 그런지는 좀더 연구해 보고 알려드리도록 하겠다. -.- 오늘은 일단 여기까지 접고 연구결과가 더 나오는대로 여러분께 보고하는 시간을 갖도록 하려한다. 

CRT Debug 기능 사용법 3 

지난번에 이어 이번에는 메모리에 어떤 문제가 있었는지를 체크해주는 _CrtCheckMemory함수에 대해 연구해 보도록 하겠습니다. 

강좌를 진행하기 전에 지난번 강좌 마지막 부분에서 메모리가 삭제될 때 0xDD값 대신에 0xFEEE값이 채워지는 이유를 찾아본 결과 CRT에서는 0xDD값을 정확히 채워 넣는다는 것을 확인하였다. _CRTDBG_DELAY_FREE_MEM_DF 플랙이 디폴트로 꺼져 있기 때문에 삭제했다는 표시를 하고 난 다음 바로 운영체제에서 삭제(진짜 삭제) 해버렸기 때문이다. 이부분은 뒤에서 다시 알아보도록 하겠다. 

_CrtCheckMemory()

지난번에 알아보기를 CRT에서 메모리를 할당하려 할 때 몇가지 정보블럭들을 설정한다는 것을 알았을것이다. 자 이제는 설정된 정보블럭들을 검사할 차례이다. 문제는 일일이 디버거의 Watch창이나 Memory창을 이용해 블록이나 스택이 깨졌는지를 확인해야 한다는 것이다. 이런 기법은 아마도 잘 알고 있을 것이다. 특정 메모리 주소를 가르키게 해놓고 의심되는 코드를 실행시켰을 때 Memory창의 내용이 빨간색으로 변하는 모양을 살펴서, 엉뚱한 부분까지 쓰거나, 원치않은 결과를 얻는지를 확인하는 것이다. 문제는 이것이 너무나도 수동적이기 때문에 CRT에서는 _CrtCheckMemory라는 도우미 함수를 곁들였다. 이 함수는 몇가지 경우에 있어서는 아주 쓸만하다. 사용법을 보자 

int _tmain(int argc, _TCHAR* argv[]) 

       if(_CrtCheckMemory() == 0) 

             return -1; 

 

       return 0; 

그냥 메모리 체크를 하기 원하는 위치에 _CrtCheckMemory함수를 삽입하기만 하면된다. 만약 0을 리턴한다면 할당된 메모리에 어떤 문제가 발생했다는 것을 의미한다. 그러나 위의 코드는 문제가 하나 있는데 바로 모든 CRT의 디버그 함수들은 DEBUG버전에서만 의미를 가지기 때문에 RELEASE버전에서는 아무 의미없는 코드가 된다는 것이다. 일단 보기에도 두 줄에 걸쳐 표기되어 있으므로 흉하다. 그러므로 다음과 같이 코딩하도록 한다. 

_ASSERTE( _CrtCheckMemory( ) ); 

_ASSERTE는 CRT에서 제공해주는 매크로이다. 또는 assert.h의 assert함수를 이용해도 좋다. MFC등을 사용한다면 ASSERT등을 사용해도 좋고 Robbins의 SUPER_ASSERT를 사용해도 좋다. 각각 약간씩의 차이점이 있기는 결과는 거의 같다. 그러니 여기서는 CRT를 사용한다는 일관성을 유지하기 위해 _ASSERTE를 사용하도록 하겠다. 

단순히 위와같이 의심갈때마다 호출해 주기만 한다면, CRT는 지금까지 등록된 모든 할당된 메모리들을 검사해 문제가 발생했는지를 확인한다. 그럼 어떤 종류의 에러들을 잡아주는지 다음의 예제들을 통해 알아보도록 하자 

예제1. 경계를 넘어서서 쓰는 경우 

int _tmain(int argc, _TCHAR* argv[]) 

       int *p = new int[10]; 

 

       p[-1] = 100; // 둘다 모두 오류이다 

       p[10] = 100; 

 

       _ASSERTE( _CrtCheckMemory( ) ); 

 

       return 0; 

위의 예제에서는 정수 타입 10개짜리 배열을 할당하고 11번째 멤버에 쓰기를 시도하였다. 이부분에는 지난 강좌에서 알려 드렸듯이 0xfd값이 채워져 있는 영역이다. 주어진 메모리 체크 함수는 0xfd값이 있어야 할 자리에 다른 값이 있는 경우 0을 리턴한다. 

예제2. 삭제된 포인터에 접근을 시도하는 경우 

int _tmain(int argc, _TCHAR* argv[]) 

 

       // _CRTDBG_DELAY_FREE_MEM_DF 플랙을 반드시 켜야된다 

       _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_DELAY_FREE_MEM_DF); 

 

       int *p = new int[10]; 

       delete [] p; 

 

       p[0] = 10; 

       _ASSERTE( _CrtCheckMemory( ) ); 

 

       return 0; 

위 예제에서는 이미 삭제된 포인터를 다시 접근하고 있다. 이것은 디폴트로 비활성화된 플랙을 사용하므로 위의 예제에서처럼 프로그램 시작전에 _CRTDBG_DELAY_FREE_MEM_DF 플랙을 켜줘야한다. 이 플랙이 켜지게 되면 CRT는 삭제 명령(free함수)이 호출되는 경우 바로 삭제처리하지 않는다. 대신 삭제 처리했다는 표시(0xdd값)만을 남겨둔다음 필요할 때 이값이 깨졌는지 검사한다. 디버그 버전이라면 이 플랙은 반드시 켜두도록 한다. 물론 메모리 부하가 약간 더 있겠지만 심각한 오류를 검출하는데는 꼭 필요한 플랙이다. 어차피 디버그 버전은 디버깅이 최고의 목표이니까.. 

이 두가지 기능만해도 일반적인 프로그래머들이 겪는 대부분의 메모리 문제는 해결된다. 아! 필자가 지금까지 봐온 대부분의 메모리 관련 문제들은 거의 60%이상이 초기화가 되지 않았거나 쓰레기값이 들어있는 포인터 접근 문제였다. 이문제는 위의 함수가 잡아주지 않는다. 그럼 쓰레기값이 들어있는 포인터 접근 문제는 어떻게 해결하겠는가? 아시는 분들은 다 아실것이다 0xC0000005 오류가 바로 정답이다. 또 대부분의 컴파일러의 경우 컴파일하는 도중에 이미 초기화 안된 변수를 사용했다고 여러분들에게 알려줄 것이다. 

다음에는 구간과 구간 사이에서 메모리 문제를 발견하는 방법에 대해 다룰 것이다. 전체 프로그램에서 문제를 발견했다면 그 범위를 점차 좁혀나가는 것이 중요하다. 아쉽지만 필자 개인적인 사정으로 인해 조금 늦어질지도 모르겠다. 

반응형
반응형

블로그 이미지

3DMP engines

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

by 송정헌






general error c101008d: Failed to write the updated manifest to the resource of file


mt.exe 와 해당 프로젝트 파일 루트 경로를 해당 프로젝트를 백신 검사에서 제외시키면 된다



mt.exe 경로는 아래이지만 개인설정에 따라 경로는 다를 수 있다


C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe

C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\x64\mt.exe

반응형
반응형

http://cs.knou.ac.kr/~khkim/faq/slist.asp?code=aa027&num=1

 

 

▣ LIB, DLL 관련 문제 해결 방법(error C3861, LNK2019, LNK1136)
▣ LIB, DLL 관련 문제 해결 방법(error C3861, LNK2019, LNK1136)

[답변] ===============================
1. error C3861:'FUNCTION_NAME()':인수 종족성을 조회해도 식별자를 찾을 수 없습니다.

-> 프로토타입 선언을 하지 않았다.
헤더나 cpp의 상단에 라이브러리 내에 존재하는 함수의 선언을 해주어야 한다.
(ex. int FUNCTION_NAME(char* str); )

2. error LNK2019: unresolved external symbol 
(또는 "외부기호를 찾을 수 없습니다.." 어쩌구.. 저쩌구..)

-> 프로젝트에 lib 파일을 링크시키지 않았다. 
메인메뉴- Project- Link(링커)- object/library modules 에다 lib파일을 추가시키자.

3. LNK1136: invalid or corrupt file Error executing link.exe.
( 또는 "파일이 잘못되었거나 손상되었습니다." )
-> object/library modules에다가 'lib'파일이 아니라 'dll'파일을 적어두지 않았는지?
굳이 dll이 아니라도 lib가 아닌 걸 쓰면 이런 에러도 뜬다. 

※ DLL을 Implicit binding으로 쓰고 싶다면 "파일명.dll"과 "파일명.lib" 둘 모두 
있어야 한다.

 

반응형
반응형

자세히 나와있는 블로그

 

http://mooyou.tistory.com/42

 

 

따라서 이를 빠르게 발견하고 해결하는 것이 중요합니다.

여기서는 C코드로 짠(콘솔 응용프로그램) 환경에서 메모리릭을 발견하고 잡는 방법을 알아보겠습니다.

다음과 같이 메인 프로젝트를 만들고 메모리릭을 감지하는 코드를 추가합니다. (강조된 부분)



// MemoryLeak.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
#include "stdafx.h"
#ifdef _DEBUG
#include <crtdbg.h>
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
int _tmain(int argc, _TCHAR* argv[])
{
#ifdef _DEBUG
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
// 메모리릭 발생코드
char * szName = new char[100];
szName = "mooyou";
printf("%s", szName);
return 0;




위의 코드를 실행하면 출력창에 메모리릭이 발생되었다고 나타납니다.

출력 정보를 보면 memoryleak.cpp 파일의 18번째 라인에서 100 bytes 크기의 메모리릭이 발생되었습니다.

이 정보만으로도 충분히 메모리릭을 잡을수 있습니다.



여기서 더 나아가 메모리 블록 위치 정보를 통해서 직접적으로 메모리릭이 발생한 코드로 이동까지 해보겠습니다.

이를위해 다음과 같이 _CrtSetDbgFlag 바로아래 _CrtSetBreakAlloc( 97 ); 코드를 추가합니다.

이는 메모리릭 발생 위치에 BreakPoint를 설정합니다.




// MemoryLeak.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
#include "stdafx.h"
#ifdef _DEBUG
#include <crtdbg.h>
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
int _tmain(int argc, _TCHAR* argv[])
{
#ifdef _DEBUG
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
_CrtSetBreakAlloc( 97 );
#endif
// 메모리릭 발생코드
char * szName = new char[100];
szName = "mooyou";
printf("%s", szName);
return 0;




즉, 출력된 메모리 블록 위치 정보를 이용하여 BreakPoint를 설정하고, 실행시 설정된 곳으로 이동하겠다라는 것입니다 !

코드를 추가하고 실행하면 다음과 같은 메시지 박스가 나타납니다.

BreakPoint에 의해 중단점을 트리거 했다라는 내용이고 여기서는 중단을 누르면 됩니다.

하지만 누르고 나서 코드를 보면 메모리릭이 발생한 원하는 위치가 아닌 dbgheap.c 파일의 내용이 보이게 됩니다.

모르는 코드화면이 나왔다고 해서 전혀 걱정할 필요가 없습니다. 정상적인 화면이고... 제대로 잘 찾아온 것입니다.

메모리릭이 발생한 곳으로 이동하려면 호출 스택에서 작업위치를 찾아가면 됩니다.

호출 스택은 보통 출력창과 같은 탭에 있고, 없다면 Ctrl + Alt + C를 눌러 호출 스택을 불러옵니다.

호출 스택은 현재 프로그램에서 실행된 명령을 순차적으로 나열한 것으로 맨 위에 찍힌 스택이 최근에 사용한 명령입니다.

현재 보이는 위치(노란색 화살표)가 msvcr100.dll로 dbgheap.c의 내용을 가르킵니다.

즉, 작업한 코드 영역이 아니죠. 따라서 작업한 영역인 MemoryLeak 스택을 더블클릭하여 이동합니다.

짜잔~ 왼쪽에 초록색 화살표가 보이시나요?

호출 스택을 이용하여 메모리릭이 발생한 위치로 이동하였습니다.




반응형
반응형

C++ 소스 에러 목록

 

1. 'strcpy': 식별자를 찾을 수 없습니다.

- strcpy 함수를 포함한 헤더 string.h를 추가해준다.

 

2. estrcpy' : 매개 변수 2을(를) 'char'에서 'const char *'(으)로 변환할 수 없습니다.

- strcpy 함수에 들어가는 문자를 문자열로 선언해준다.

 

3. 'init' :참조되지 않은 지역 변수입니다.

- 사용되지 않는 변수이므로, 삭제해준다.

 

4. 구문 오류 : ')'이(가) '문자열' 앞에 없습니다.

- ')' 가 빠졌으므로, 빠진 위치에 적절히 추가해준다.

 

5. 'fopen' : 함수는 1개의 매개 변수를 사용하지 않습니다.

- fopen 에는 2가지 파라메터가 필요하다. 반드시 2가지를 추가해주도록 한다.

 

6. 'p_' : 선언되지 않은 식별자입니다.

- p_를 사용하기전에 이것이 무엇인지 반드시 선언해주어야한다.

 

7. 구문 오류 : ';'이(가) ')' 앞에 없습니다.

- ';' 가 빠졌으므로, 빠진 위치에 적절히 추가해준다.

 

8. '=' : 'char'에서 'char [100]'(으)로 변환할 수 없습니다.

- 등호 표시 '=' 는 양쪽이 같은 형일때만 사용할 수 있다. 양쪽을 같게 바꿔준다.

 

9. 'delete' : 포인터가 아닌 개체를 삭제할 수 없습니다.

- delete를 사용하는 개체가 포인터인지 확인하고 포인터가 아닐 시 해당 라인을 제거한다.

 

10. 'fprintf' : 매개 변수 1을(를) 'const char [9]'에서 'FILE *'(으)로 변환할 수 없습니다.

- fprintf 맨 앞에 파일 포인터 값을 넣어준다.

 

11. 구문 오류 : ')'이(가) 'return' 앞에 없습니다.

- return 구문 앞에 )를 삽입하여 블록을 닫아준다.

 

12. 오버로드된 'operator ->'의 'StudentInfo **' 반환 형식이 잘못되었습니다.

- -> 연산자를 사용하기 위해 사용된 변수를 포인터로 사용했는지 확인한다.

 

13.'student_number' : 'std::list<_Ty>::_Iterator<_Secure_validation>'의 멤버가 아닙니다.

- student_number 가 포인터의 멤버가 맞는지 확인한다.

 

14. '초기화 중' : 'std::list<_Ty>::_Iterator<_Secure_validation>'(으)로 변환할 수 없습니다.

- iterator을 호출한 개체에 '*' 가 붙어있는지 확인한다.

 

15. 이항 '!=' : 오른쪽 피연산자로 연산자가 없거나 허용되는 변환이 없습니다.

- iterator을 호출한 개체에 '*' 가 붙어있는지 확인한다.

 

16. 'StudentInfo' 형식에 오버로드된 멤버 'operator ->'가 없습니다.

- iterator을 호출한 개체에 '*' 가 붙어있는지 확인한다.

 

17. '->StudentInfo::student_number' : 왼쪽 피연산자에 'struct' 형식이 있습니다. '.'를 사용하십시오.

- '->' 포인터 호출 기호 대신 '.'  스트럭트 호출 기호로 바꿔서 사용한다.

 

18. 첨자는 배열 또는 포인터 형식을 사용해야 합니다.

- 첨자에 []를 붙이거나 *를 붙여준다.

 

19. 구문 오류 : ';'이(가) ')' 앞에 없습니다.

- ';' 가 빠졌으므로, 빠진 위치에 적절히 추가해준다.

 

20. 구문 오류 : ')'이(가) 'return' 앞에 없습니다.

- return 구문 앞에 )를 삽입하여 블록을 닫아준다.

 

21. 'jeongsu' : 선언되지 않은 식별자입니다.

- jeongsu를 사용하기전에 이것이 무엇인지 반드시 선언해주어야한다.

 

22. 'int'에서 'bool'(으)로 잘립니다.

- bool 로 선언된 것을 int 형으로 바꿔준다.

 

23. 왼쪽 피연산자는 l-value이어야 합니다.

- 왼쪽에 있는 피연사자를 상수가 아닌 변수로 바꿔준다.

 

24. '->student_number' 왼쪽은 클래스/구조체/공용 구조체/제네릭 형식을 가리켜야 합니다.

- student_number를 호출한 것이 무엇인지 확인하고 클래스/구조체/공용 구조체로 바꿔준다.

 

25. '->height' 왼쪽은 클래스/구조체/공용 구조체/제네릭 형식을 가리켜야 합니다.

- height를 호출한 것이 무엇인지 확인하고 클래스/구조체/공용 구조체로 바꿔준다.

 

26. 구문 오류 : '>'

- <> 안에 들어간 것이 무엇인지 확인하고 매개 변수로 올바르게 바꿔준다.

 

27. 'std' : 클래스 또는 네임스페이스 이름이 아닙니다.

- "stdlib.h" 헤더를 include 시켜준다.

 

28. 'iterator' : '`global namespace''의 멤버가 아닙니다.

- iterator을 호출한 매개 변수가 올바르게 사용되었는지 확인한다.

 

29. 'Compare2' : 값을 반환해야 합니다.

- return 구문을 붙여 함수에 맞는 값을 반환해준다.

 

30. 'fopen' : 함수는 1개의 매개 변수를 사용하지 않습니다.

- fopen 에 2개의 파라메터 값을 삽입해준다. 파일포인터, 파일모드의 2개.

 

31. '->std::list<_Ty>::push_back' : 왼쪽 피연산자에 'class' 형식이 있습니다. '.'를 사용하십시오.

- push_back 왼쪽에는 클래스 형식에 알맞는 '.' 기호를 사용한다.

 

32. 'std::list<_Ty>' 형식에 오버로드된 멤버 'operator ->'가 없습니다.

- 특정 함수를 호출할 때 사용되는 연산자가 '->' 로 잘못 사용되었으므로 '.' 로 바꿔준다.

 

33. 'getch': 식별자를 찾을 수 없습니다.

- conio.h 헤더를 include 해준다.

 

34. 이전 오류를 복구할 수 없습니다. 컴파일이 중지됩니다.

- 상위에 생긴 C++ 소스 에러를 모두 올바르게 수정하고 컴파일을 다시 시도한다.

 

35. 구문 오류 : ']'

- [] 표시가 제대로 열리고 닫혔는지 확인해준다.

 

36. 'fopen': This function or variable may be unsafe. Consider using fopen_s instead.

- 새로운 C++ 에서는 각 상황에 알맞는 형식의 내장함수가 새로 추가되었다. 상황에 맞게 바꿔주도록한다.

 

37. 'fscanf': This function or variable may be unsafe. Consider using fscanf_s instead.

- 새로운 C++ 에서는 각 상황에 알맞는 형식의 내장함수가 새로 추가되었다. 상황에 맞게 바꿔주도록한다.

 

38. 'printf': This function or variable may be unsafe. Consider using printf_s instead.

- 새로운 C++ 에서는 각 상황에 알맞는 형식의 내장함수가 새로 추가되었다. 상황에 맞게 바꿔주도록한다.

 

39. 'scanf': This function or variable may be unsafe. Consider using scanf_s instead.

- 새로운 C++ 에서는 각 상황에 알맞는 형식의 내장함수가 새로 추가되었다. 상황에 맞게 바꿔주도록한다.

 

40. 'StudentInfo' 다음에 'bool'이(가) 올 수 없습니다. ';'이 있어야 합니다.

- StudentInfo 뒤에 ; 종결문이 제대로 적혀있는지 확인하고 추가해준다.

 

41. 'return' : 'bool'에서 'StudentInfo'(으)로 변환할 수 없습니다.

- return 반환하는 부분에 bool 로 선언된 것이 올바른 것이 확인해준다.

 

42. 구문 오류 : ';'이(가) '}' 앞에 없습니다.

- ';' 기호가 제대로 적혀있는지, 위치를 확인한다.

 

43. 구문 오류 : '>'

- > 연산자가 올바르게 사용되었는지 확인한다. 대소 비교에 사용된다.

 

44. 'sqrt' : 오버로드된 함수에 대한 호출이 모호합니다.

- 제곱근을 구하는 함수에 인수를 double 형으로 임시 선언해준다.

 

45. 이항 '!=' : 오른쪽 피연산자로 연산자가 없거나 허용되는 변환이 없습니다.

- 오류가 난 줄의 != 연산자 좌우의 형을 비교하고 같은것인지 확인한다.

 

46. '<' : 의미 없는 연산자입니다. 파생 작업이 있는 연산자여야 합니다.

- < 연산자를 사용하기 이전에 그 바로 전의 연산이 제대로 되어있는지 확인한다.

 

47. 초기화되지 않은 'dummyDay' 지역 변수를 사용했습니다.

- dummyDay의 초기값을 설정해준다.

 

48. 'Sort': 식별자를 찾을 수 없습니다.

- Sort 함수를 메인함수 위에 적어, preprocessing 해준다.

 

49. 'gets': This function or variable may be unsafe. Consider using gets_s instead.

- 새로운 C++ 에서는 각 상황에 알맞는 형식의 내장함수가 새로 추가되었다. 상황에 맞게 바꿔주도록한다.

 

50. 'strcmp' : 매개 변수 1을(를) 'char [1][1]'에서 'const char *'(으)로 변환할 수 없습니다.

- 매개 변수를 임시로 (const char*) 로 선언해준다.

 

51. 'double'에서 'float'(으)로 잘립니다.

- float 으로 사용되는 것을 double 로 확장해준다.

 

52. 'temp' :참조되지 않은 지역 변수입니다.

- temp 는 사용되지 않는 변수이므로 삭제해주도록 한다.

 

53. 상수에 줄 바꿈 문자가 있습니다.

- 상수가 올바르게 상수만 적혀있는지 확인한다.

 

54. 'y' : 선언되지 않은 식별자입니다.

- y 로 선언된 변수가 있는지, 오타인지 확인한다.

 

55. ';' : 제어된 빈 문이 있습니다. 이 문이 필요합니까?

- 아무 명령이 없는 문장이므로 삭제해준다.

 

56. 'menu' 레이블이 정의되지 않았습니다.

- goto 문에 사용될 레이블의 위치를 지정해준다.

 

57. 'Sort' : 함수는 3개의 매개 변수를 사용하지 않습니다.

- Sort 라고 정의된 함수가 사용하는 매개 변수의 갯수에 따라 소스를 수정해준다.

 

58. 구문 오류 : int'은(는) ';' 다음에 와야 합니다.

- int 앞에 ';' 기호가 제대로 적혀있는지 확인하고 추가해준다.

 

59. 함수 호출에 인수 목록이 없습니다. '&std::list<_Ty>::size'을(를) 사용하여 멤버에 대한 포인터를 만드십시오.

- size 라는 함수가 ()를 붙여 포인터로 만들어서 사용되었는지 확인한다.

 

60. '<=' : 'int'에서 'unsigned int (__thiscall std::list<_Ty>::* )(void) const'(으)로 변환되지 않았습니다.

- '<=' 연산자 양쪽의 변수 형이 'int' 로 같게 맞춰준다.

 

반응형
반응형

1. 프로젝트 속성 --> C/C++ --> 일반-->
디버깅 정보형식 에서 --> 프로그램 데이타 베이스를 선택한다. ( 원래는 사용 않함 )
2. 프로젝트 속성 --> 링커 --> 디버깅-->
디버깅 정보생성 --> 예/DEBUG 선택한다. ( 원래는 아니오 )
3. 솔류션 정리
4.솔루션 다시빌드

반응형
반응형

google_protectAndRun("render_ads.js::google_render_ad", google_handleError, google_render_ad);
VB로 만든 프로젝트 솔루션에
MFC로 만든 프로젝트를 몇개 추가하고
빌드 모드를 기본 DEBUG와 RELEASE말고 하나 더 추가하여
컴파일 했더니 MFC프로젝트는 안되더라
검색해도 나오지도 않고 이상한 이야기만 하더라

답은 간단했다.

솔루션-마우스 우클릭-속성-구성속성-구성-빌드탭의 체크박스를 모두 체크해주자

반응형
반응형

첨부파일 mt.exe


http://coinz.tistory.com/455

아래처럼 해도 안되면 프로젝트 안에 빌드한 폴더안에 mt.exe 를 복사해 넣으면됨

반응형
반응형

http://godsfly.blog.me/130089798487



header 추가

#ifdef _DEBUG
#define CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif

WinMain() 함수에 
_CrtDumpMemoryLeaks();
Function Call

위와 같이 실행 할 경우 Debug모드로 실행 후 종료 시  아래와 같은 메시지 출력된다.
Detected memory leaks!
Dumping objects ->
{57} normal block at 0x003E5D38, 36 bytes long.
 Data: <                > 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 
{56} normal block at 0x003E5BF0, 268 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD 
Object dump complete.
---------------------------------------------------------------------------------------
메모리 누수 검출 방법

1. 함수를 이용한 메모리 누수 검색방법

영역표시된 부분(57)이 메모리 누수가 발생하는 프로그램 주소값이다. 이 주소 값을 이용하여
_crtSetBreakAlloc(56);
라는 함수 파라미터 값으로 주소 값을 입력하게 되면 메모리 할당 및 메모리 위치, 메모리 누수 위치는 중단점에서 멈추게 된다.

2. Visual Studio 에 있는 기능을 이용한 검색 방법


영역표시된 부분이 메모리 누적이 발생한 위치값이다.
이것을 Ctrl + B를 누르게 되면 새 중단점을 지정할 수 있다.



위와 같이 설정 후 확인을 누르게 되면 메모리 누수가 발생하는 곳에서 멈추게 된다.

※ 주의사항 : 이 중단점(Break Point)는 Visual Studio에서 표시가 이루어지지 않는다. 그렇기 때문에 설정된 중단점을 삭제하기 위해서는  모든 중단점 해제(ctrl + shift + F9)로 중단점 해제해야 한다.
그렇지 않으면 매번 디버그 할때마다 같은 지역에서 멈추게 된다.

반응형
반응형


원인
new
malloc 로 메모리를 할당하여 사용한후,
메모리에서 해당영역을 해지하지 않게 되면 메모리부족 현상이 발생하게 된다.

현상
VS 로 디버깅을 한번이라도 해봤다면 아래와 같은 메세지를 본 적이 있을 것이다.

{67} normal block at 0x00032528, 68 bytes long.
Data: < & X' ' > 10 00 00 00 C0 26 03 00 58 27 03 00 E8 27 03 00

{68} normal block at 0x000322A2, 62 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD

이는 CRT(C Runtime Library)에서 메모리 누수를 감지하여 화면에 보여주는 것인데, 메모리를 할당한후 해제하지 않았음을 보여준다.
간단하게 살펴보면,
{67} 은 메모리가 할당된 순서이고,
0x00032528 는 메모리 주소이고,
Data: < 는 메모리에 있는 실제 데이터의 내용이다.

하지만 위의 메세지로는 아무것도 할수가 없다. 도대체 더 문제가 어디서 발생했는지 알 방법이 없다.
만약 코드가 길지 않다면, 천천히 재검토하여 찾아낼수 있겠지만,
코드의 길이가 길 경우, 일일히 다 찾아볼수 없는 노릇이다.
(프로그램은 시간과의 싸움인데, 디버깅하다 시간을 다 보낼수 없는 것이다.)

처리방법
이럴때 어떻게 해야 해야 할까?
다행히 VS 에서는 메모리 누수를 간단한 방법으로 감지할수 있게 도와 주는 기능이 있다.
(디폴트 값으로 사용안함으로 되어 있기 때문에 잘 모르는 사람이 많고, 이 기능을 이용하면,
메모리 누수가 탐지된 파일과 라인을 알수 있다.)


<stdafx.h> 파일의 상단에
#define _CRTDBG_MAP_ALLOC
를 추가하고,
메모리 누수 탐지를 시작할 부분에
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
를 추가해주면 끝이다.


_CrtSetDbgFlag(..):
CRT디버거의 플래그 설정함수.
파라미터에 따라 디버깅 옵션이 달라지므로 주의해야 한다.
CRTDBG_ALLOC_MEM_DF : 디폴트로 켜져 있으며, DEBUG MODE 에서 모든 메모리 할당이 일어날 때마다 메모리 메세지를 알리게 하는 옵션이다. 이 플래그는 당연히 항상 ON 해야 한다.
_CRTDBG_DELAY_FREE_MEM_DF : delete, free등으로 삭제할때 메모리에서 바로 삭제되지 않고, CRT에서 보관하다가 프로그램 종료시에 완전히 삭제된다.
_CRTDBG_CHECK_ALWAYS_DF : 모든 메모리관련 연산에서 _CrtCheckMemory를 호출한다.
_CRTDBG_CHECK_CRT_DF : CRT가 내부적으로 할당한 블록도 메모리를 체크할 때 사용한다. 일반적으로 사용하지 않는다
_CRTDBG_LEAK_CHECK_DF : 프로그램이 종료되기 직전에 아직 해제되지 않은 메모리를 있는지 검사한다.


반응형
반응형

http://blog.naver.com/kimig82?Redirect=Log&logNo=80086088092

3.2 메모리릭 발생 위치에 Breakpoint 설정하기 #

메모리릭이 발생하면 디버거를 종료했을 때 이런 메시지가 출력된다.
Detected memory leaks! Dumping objects -> {103144} normal block at 0x01C79B18, 12 bytes long. Data: < > 18 9B C7 01 18 9B C7 01 CD CD CD CD 
왠만하면 어느 파일의 몇 번째 줄에서 메모리릭이 발생했다고 알려주지만, 이 경우처럼 디버거가 알려주지 못하는 경우도 많고, for문 안에서 메모리릭이 발생하는 경우처럼 위치만 알아서는 정확히 언제 발생하는지 알기 어려울 때도 있다. 이럴 때 사용할 수 있는 것이 중괄호안에 들어있는 숫자다. 이 숫자는 메모리 할당 번호(Memory Allocation Number)인데, 번호가 103144라는 것은 이 프로그램에서 할당받은 메모리 중에서 103144번째 블록이라는 뜻이다(헉... 내 프로그램이 메모리를 이렇게 많이 할당받았던가 -0-;;).

프로그램 코드의 적당한 위치에
_crtBreakAlloc = 103144; 
라고 적어주고 디버거를 실행하면 이 메모리를 할당하려고 할 때 프로그램을 Break 시켜준다. 디버그 버전에서는 힙에 메모리를 할당할 때마다 crtdbg 라이브러리(이렇게 표현해도 되나?)가 이 변수를 체크해서 Break 해주는 것이다. 디버깅중에 Watch 윈도우에서 변수 값을 바꿔서 다른 메모리 할당 번호에서 멈출 수도 있다. 전역 변수 값을 변경하는 대신에
_CrtSetBreakAlloc(103144); 
라고 함수를 호출해주어도 마찬가지 효과가 있다.

MSDN 기술문서 중 "Detecting and Isolating Memory Leaks"를 참고했음.

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

Visual Studio 디버거
방법: 메모리 할당 번호에 중단점 설정

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

Visual Studio Edition

Visual Basic

C#

C++

J#

Express

아니요

아니요

Native

아니요

Standard

아니요

아니요

Native

아니요

Pro/Team

아니요

아니요

Native

아니요

Note참고

실제 설정이나 버전에 따라서 화면에 나타나는 대화 상자와 메뉴 명령이 도움말의 설명과 다를 수 있습니다. 설정을 변경하려면 도구 메뉴에서 설정 가져오기 및 내보내기를 선택합니다. 자세한 내용은 Visual Studio 설정을 참조하십시오.

메모리 누수 보고서에 있는 파일 이름과 줄 번호를 보면 누수된 메모리가 할당된 위치를 알 수 있습니다. 그러나 메모리 할당 위치를 안다고 해서 반드시 문제를 식별할 수 있는 것은 아닙니다. 프로그램을 실행하는 도중에 할당이 여러 번 호출되지만 특정 호출에 대해서만 메모리 누수가 발생할 수 있습니다. 문제를 식별하려면 누수된 메모리가 할당된 위치와 누수 발생 조건을 알아야 합니다. 그러기 위해서는 메모리 할당 번호가 필요합니다. 메모리 할당 번호는 파일 이름과 줄 번호 다음의 중괄호에 표시됩니다. 예를 들어, 다음 출력에서 메모리 할당 번호는 18입니다. 이는 누수된 메모리가 18번째로 프로그램에 할당된 메모리 블록임을 뜻합니다.

Detected memory leaks!
Dumping objects ->
C:\PROGRAM FILES\VISUAL STUDIO\MyProjects\leaktest\leaktest.cpp(20) : {18} 
normal block at 0x00780E80, 64 bytes long.
 Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

프로그램을 실행하는 동안 CRT 라이브러리는 CRT 라이브러리나 MFC와 같은 다른 라이브러리가 할당한 메모리를 비롯하여 할당된 모든 메모리 블록을 계산합니다. 따라서 할당 번호가 N인 개체는 프로그램에 할당된 N 번째 개체입니다. 그러나 코드에서 할당한 N 번째 개체는 아닐 수도 있습니다. 대부분의 경우 그렇지 않습니다.

할당 번호를 사용하여 메모리가 할당된 위치에 중단점을 설정할 수 있습니다. 먼저 프로그램의 시작 부분에 위치 중단점을 설정하십시오. 이 위치에서 프로그램이 중단되면 간략한 조사식 대화 상자나 조사식 창에서 메모리 할당 중단점을 설정할 수 있습니다.

프로시저

조사식 창에서 메모리 할당 중단점을 설정하려면

  1. 조사식 창에서 이름 열에 다음 식을 입력합니다.

    _crtBreakAlloc

    CRT 라이브러리의 다중 스레드 DLL 버전을 사용할 경우(/MD 옵션) 다음과 같이 컨텍스트 연산자를 포함해야 합니다.

    {,,msvcr71d.dll}_crtBreakAlloc
  2. RETURN 키를 누릅니다.

    디버거에서 호출을 계산하고 값 열에 결과를 표시합니다. 메모리를 할당할 때 중단점을 설정하지 않은 경우에는 이 값이 –1입니다.

  3. 열에 있는 값을 중단할 메모리 할당 번호로 대체합니다. 예를 들어, 위의 출력에서는 중단할 메모리 할당 번호가 18입니다.

원하는 메모리 할당에 중단점을 설정한 다음 디버깅을 계속할 수 있습니다. 이전과 같은 조건에서 프로그램을 실행하려면 할당 순서가 변경되지 않도록 주의하십시오. 지정된 메모리 할당에서 프로그램이 중단되면 호출 스택 창과 다른 디버거 정보를 살펴 보고 메모리가 할당된 조건을 확인할 수 있습니다. 필요한 경우 해당 지점에서 프로그램을 계속 실행하면 개체의 진행 상황과 할당 취소가 제대로 이루어지지 않는 이유도 알 수 있습니다.

Note참고

개체에 데이터 중단점을 설정하는 것이 좋습니다. 자세한 내용은 방법: 데이터 중단점 설정(네이티브 전용)을 참조하십시오.

대개 디버거에서 메모리 할당 중단점을 설정하는 것이 더 쉽지만 경우에 따라 코드에서 설정할 수도 있습니다.

코드에서 메모리 할당 중단점을 설정하려면

  • 다음과 같은 줄을 추가합니다(열 여덟째 메모리 할당인 경우).

    _crtBreakAlloc = 18;

_CrtSetBreakAlloc 함수를 대신 사용해도 같은 효과가 있습니다.

_CrtSetBreakAlloc(18);

참고 항목

반응형
반응형

아래 포스트에서는

해당 변수의 값에 대해 메모리 창에서 주소를 복사해 가지면

해당변수이름 앞에 & 를 붙여 조건석이 넣는 것도 가능하다


http://jeylee1031.tistory.com/entry/visual-studio-2008-debug-tip

코드와 같이 i 가 100일 경우 전역 변수 n의 값을 바꾸는 코드입니다..

지금 보시기에는 간단하지만 이러한 형태로

실무에서 상당히 유용하게 사용하실 수 있습니다.

사용하는 방법은 위와 같이 무조건 일단 break를 걸어놓습니다..

전역 변수 n의 주소 값을 확인합니다..

그냥 조사식 창에서 확인하시면 되겠죠..


순환문에서와 동일하게 중단점 창에서 '조건'을 선택합니다.


아까 확인하신 메모리 주소로 조건창에 적어주고 라디오 버튼을 '변경된 경우'를 선택합니다.

그리고 확인을 누르세요..


그리고 다시 F5를 누르시면 n이 변경된 이후 시점으로 멈춥니다..

6.0에서는 정말 전역적으로 체크가 가능했는데,

제가 무엇을 부족하게 아는것인지..

2008에서는 for문 안에서만 가능하네요..

자세하게 알면 다시 포스팅하겠습니다..

반응형
반응형

http://nicecapj.blog.me/130022161118


위 블로그에서는 덤프파일로 사용자컴(프로그램을 돌리는 실제 하는 사용자)에서 버그가 발생할경우에 대한 덤프 파일을 만들고

그 덤프파일을 바탕으로 vs 에서 디버깅 할 수 있는 환경을 재생시켜주는 환경을 브레이크 걸어 보여준다






[디버그]미니덤프를 사용한 Crash잡기(의역)  디버깅 

2007/09/08 16:16

복사http://nicecapj.blog.me/130022161118



CrashDump 라는 프로젝트를 생성하고, 위와 같이 간단한 소스를 코딩磯?lt;/P>

p는 포인터 변수로(const char* p) 현재 NULL값을 가지고 있다.

그 후, NULL을 가르키고 있는 포인터 변수의 값을 출력하게 함으로써, 문제를 일으키는 소스이다 

 

 

예상했던 되로, 컴파일 해서 실행을 하면 문제를 일으키게 된다 . 이때 우리는 디버그 모드임으로 콜스택의 상태와 문제가 생긴 부분을 볼수 있다. pdb 파일에 디버깅 정보가 기록되 있기 때문이다.

 

 

죽은 부분은 NULL포인터의 주소(0X00000000)을 가르키고 있다. 우리는 콜스택의 상태나, 문제 부분의 값을 볼수 있지만 사용자에게 사용할 때는 그렇지 않다.

 

 

이제부터 윈도우의 닥터 왓슨32를 이용해서 문제를 잡아보도록 하자

닥터 왓슨 32를 실행하자

 

 

여러가지 옵션값이 있는데 우리는 모두 체크하도록 하자. 내용을 모두 한글로 적을까 하였으나, 보통 한글 윈도우를 사용할 것이라 생각하고, 영어 내용도 어려운 내용은 없음으로 생략한다. 중요한 것은 로그파일 패스와, 생길 덤프 파일의 이름 설정정도이다.

 

 

자 이제 실제로 프로그램의 문제가 생겼을때, 닥터왓슨이 이를 처리하도록 해주는 작업을 해야한다

regedit로 레지스트리 에디터를 연후 HKEY_LOCAL_MACHINE -> SOFTWARE -> Microsoft -> Windows NT -> CurrentVersion-> AeDebug 를 열어서 drwtsn32.exe -p %ld -e %ld -g로 설정하도록 하자. 보통 비쥬얼 스튜디오가 설치된 분들은 비쥬얼 스튜디오가 문제 발생시 처리하게 되 있을 것이다. 프로그램이 이상을 일으켰을때 DEBUG 하시겠습까? 라는 부분이 이에 해당한다

 

 

설정은 저장한 후, 다시 CrashDump.exe를 실행해보자. 그러면 닥터왓슨이 로그를 기록했다는 메시지를 볼 수 잇다.

 

로그 파일의 내용은 문제가 발생한 어플리케이션, 스택, 발생당시 메모리상의 프로세스들 등의 정보를 담고 있다.

 

 

 

 

그럼 문제 발생시 닥터 왓슨이 생성해준 덤프를 우리가 만든 CrashDump 프로젝트에 debug 폴더로 복사하도록 하자. 이 분도 Total Commander을 사용하고 있는 모습이 인상적이었다. 어쨋든 복사하도록 하자

 

 

복사한 후에 비쥬얼 스튜디오에서 File->OpenProject를 선택하여 dump파일을 열도록 한다

 

 

dump파일을 열면 새로운 프로젝트가 생기는데, 여기서 Debug->Start New Instance를 선택한다

 

 

프로젝트가 실행이 되고, 소스코드와 매칭되어, 문제가 발생하는 부분에서 디버깅을 시작할 수 있다.

 

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

출처 : MSDN - VIsual c++ home의 David Ching이 기고하신 글

:Track('ctl00_ctl01|ctl00_ctl03',this);" href="http://download.microsoft.com/download/e/c/2/ec221dcb-e0f1-4cda-a252-a6eab3fc75a4/winvideo-nativecoding-crashdump.wmv" >How Do I: Create and Analyze a Mini-Dump File in Windows?
 
:Track('ctl00_ctl01|ctl00_ctl04',this);" href="http://download.microsoft.com/download/e/c/2/ec221dcb-e0f1-4cda-a252-a6eab3fc75a4/winvideo-nativecoding-crashdump.wmv">Mini-dumps contain pertinent data during a crash. When analyzed in Visual Studio, they show the call stack and symbols, just as if the crash had occurred on the developer's machine while debugging within Visual Studio. Mini-dumps are captured in Windows XP and Windows Vista without requiring Visual Studio or any other tool to be installed or running.

Presented by David Ching on September 4, 2007
Length: 18 minutes 22 seconds
 
Video Downloads: 
:Track('ctl00_ctl01|ctl00_ctl05',this);" href="http://download.microsoft.com/download/e/c/2/ec221dcb-e0f1-4cda-a252-a6eab3fc75a4/winvideo-nativecoding-crashdump.wmv" >WMV | :Track('ctl00_ctl01|ctl00_ctl06',this);" href="http://download.microsoft.com/download/e/c/2/ec221dcb-e0f1-4cda-a252-a6eab3fc75a4/ipod-nativecoding-crashdump-0.mp4">iPod | :Track('ctl00_ctl01|ctl00_ctl07',this);" href="http://download.microsoft.com/download/e/c/2/ec221dcb-e0f1-4cda-a252-a6eab3fc75a4/mp4video-nativecoding-crashdump-1.mp4" >MP4 | :Track('ctl00_ctl01|ctl00_ctl08',this);" href="http://download.microsoft.com/download/e/c/2/ec221dcb-e0f1-4cda-a252-a6eab3fc75a4/3gpvideo-nativecoding-crashdump.3gp" >3GP | :Track('ctl00_ctl01|ctl00_ctl09',this);" href="http://download.microsoft.com/download/e/c/2/ec221dcb-e0f1-4cda-a252-a6eab3fc75a4/zune-nativecoding-crashdump-0.wmv" >Zune | :Track('ctl00_ctl01|ctl00_ctl10',this);" href="http://download.microsoft.com/download/e/c/2/ec221dcb-e0f1-4cda-a252-a6eab3fc75a4/pspvideo-nativecoding-crashdump.zip">PSP
 
Audio Downloads: 
:Track('ctl00_ctl01|ctl00_ctl11',this);" href="http://download.microsoft.com/download/e/c/2/ec221dcb-e0f1-4cda-a252-a6eab3fc75a4/aacaudio-nativecoding-crashdump.aac" >AAC | :Track('ctl00_ctl01|ctl00_ctl12',this);" href="http://download.microsoft.com/download/e/c/2/ec221dcb-e0f1-4cda-a252-a6eab3fc75a4/winaudio-nativecoding-crashdump.wma">WMA | :Track('ctl00_ctl01|ctl00_ctl13',this);" href="http://download.microsoft.com/download/e/c/2/ec221dcb-e0f1-4cda-a252-a6eab3fc75a4/mp2audio-nativecoding-crashdump.mp2" >MP2 | :Track('ctl00_ctl01|ctl00_ctl14',this);" href="http://download.microsoft.com/download/e/c/2/ec221dcb-e0f1-4cda-a252-a6eab3fc75a4/mp3audio-nativecoding-crashdump.mp3" >MP3 | :Track('ctl00_ctl01|ctl00_ctl15',this);" href="http://download.microsoft.com/download/e/c/2/ec221dcb-e0f1-4cda-a252-a6eab3fc75a4/mp4audio-nativecoding-crashdump.m4a" >MP4  
 
:Track('ctl00_ctl01|ctl00_ctl16',this);" href="http://download.microsoft.com/download/e/c/2/ec221dcb-e0f1-4cda-a252-a6eab3fc75a4/samplecode-nativecoding-crashdump.zip">Download the code

반응형
반응형

http://blog.naver.com/ysoftman/20068970629

Just In Time Debugger 를 무시하기 위해

도구->옵션 -> 디버깅 - Just In time 의 항목들을 비활성화시킴

반응형
반응형

-디버거가 작동하지 않는경우

-중단점이 활성화되지 않는 경우

-visual studio 가 죽어버리는 경우

.suo 파일을 삭제한후 다시 열어본다

.suo 파일은 파일 목록과 중단점, 조사식 창의 내용 등을 포함하고 있다

반응형
반응형

http://kldp.org/node/84549


안녕하세요

여러사람이 오랜기간 한 코드를 (잘못)관리하다 보니

프로젝트 내에 선언만 하고 사용하지 않는 함수라던지 객체들이 많이 산제되어 있습니다.

일일이 함수 이름으로 find 해서 찾기에는 시간이 많이 걸리는데요

혹시 쉽게 찾을수 있는 방법이 있을까요?

헤더파일의 경우 include만 해두고 사용하지 않는 것들을 찾아주는 툴(찾아서 주석처리해줍니다)을 보긴했으나

함수에 대해서는 본적이 없는것 같아서요

비회원
손님





올리기Visual Assist X 를 사용해보세요 올려짐: 2007-07-19 12:20
인용과 함께 답변 이 게시물을 del.icio.us에 추가

Visual Assist X 를 사용해보세요. 함수에 놓고 Find Reference 리팩토링 명령을 하면, 그 함수의 문맥에 맞는 참조들을 찾아줍니다.
위로
비회원
손님





올리기데브파트너 올려짐: 2007-07-19 13:44
인용과 함께 답변 이 게시물을 del.icio.us에 추가


코드 커버리지로 놓고 실행하면, 0번 실행한 라인부터 가장 많이 실행한 라인까지 다 찾아줍니다.

반응형
반응형

복사http://blog.naver.com/yiyunju/150036349714

전용뷰어

vs2005에서 소스를 컴파일 할 때 마지막 때쯤에 "IntelliSense를 업데이트 하고 있습니다"라는 문구를 볼 수 있다..

그렇다면 IntelliSense란 무엇인가?

 

IntelliSense기능은 소스코드뷰에서 클래스나 함수, 변수등을 오른쪽마우스로 클릭하여  원하는 컨텍스트(Parameter Info, Type Info, 

Go To Definition 등)를 선택할 경우 해 당 개체에 대한 정보를 알려주거나 정보가 있는 위치로 이동시키는 것을 말한다
또한 클래스나 구조체의 변수나 포인터 변수의 오른쪽에 "." 이나 "->"을 타이핑할 경우 클래스의 멤버함수와 프라퍼티, 구조체의 멤버에 대한 내용이 자동으로 출력되는데 바로 이 기능 역시 인텔리전스의 기능이다.
IntelliSense는 클래스, 함수, 변수, 구조체에 대한 직관적인 정보를 제공하기 위한 메 카니즘입니다. 중요한 것은 IntelliSense기능을 구현하기 위한 데이터파일이 존재하는데. 작업프로젝트 디렉토리에 있는 *.ncb파일이다.이 파일을 지운 후  VS를 재시동하면 새로 업데이트된 새 파일이 생성되고. 이 후에는 모든 동작이 정상적으로 이루어진다..


그러나 이 기능은 일정 시간동안은 제대로 작동하다가 프로젝트에 포함된 파일을 제거하 거나 수정하거나 하는 등 여러 가지 작업을 하다보면 때때로 이 기능 때문에 컴퓨터가 눈에 띄게 버벅거리게 되는데

 

이를 해결하기 위해서??

그래서 나 같은 경우에는 따로 visual assist를 설치하여 vs2005에 내장되어 있는 인텔리젼스 기능을 쓰지 않는다.

C:\Program Files\Microsoft Visual Studio 8\VC\vcpackages\feacp.dll 이 파일을 다른 이름으로 변경 해 놓으면 된다.

 

 아니면 아예 인텔리젼스 기능을 쓰지 않게 하려면  기본적으로 IntelliSense 옵션 설정을 해제하려면 다음과 같이 하면 된다.

==================================================================
도구 메뉴에서 옵션을 클릭합니다.

텍스트 편집기 폴더를 선택합니다.

IntelliSense를 사용자 지정할 언어의 폴더를 선택합니다.

일반 속성 페이지에서 원하지 않는 IntelliSense 기능에 대한 확인란 선택을 취소합니다.

멤버 목록 자동 표시는 멤버 목록에 적용됩니다.

매개 변수 정보는 매개 변수 정보에 적용됩니다.

반응형

+ Recent posts