레이블이 MFC인 게시물을 표시합니다. 모든 게시물 표시
레이블이 MFC인 게시물을 표시합니다. 모든 게시물 표시

Visual C++ Detected memory leaks debugging

'Detected memory leaks!' 즉 메모리가 누수시 AfxSetAllocStop(number) 이용하면 쉽게 디버깅이 가능하다.
만약 출력창에 다음과 같이 메모리 누수가 나타나면
Dumping objects ->
{1359} normal block at 0x0139D7D8, 332 bytes long.
 Data: <                > 00 00 00 00 CD CD CD CD 00 00 00 00 00 00 00 00 
{1358} normal block at 0x0139D758, 64 bytes long.
 Data: <d:\Project\OCR-N> 64 3A 5C 50 72 6F 6A 65 63 74 5C 4F 43 52 2D 4E 

소스 코드 시작지점(main, init. 생성자....등)에서 {} 안에 있는 숫자를 파라미터로 설정하여 다음과 같이 사용한다.
AfxSetAllocStop(1359);

그리고 나서 F5 로 디버깅을 시작하면 메모리를 공간을 확보하는 시점(new, alloc()...)에 브레이크포인트가 걸린다.
이후 호출스택을 보면 어느시점에서 어떤 녀석이 메모리를 사용하려고 하는지 알수 있다.
결국 그 어떤 녀석이 나중에 메모리 해제가 안되는 것으로 파악되고 코드를 수정하면 된다.
AfxSetAllocStop 는 MFC 환경에서 사용되는 함수이다. 만약 MFC 환경이 아니라면 다음과 같이 _CrtSetBreakAlloc() 를 사용한다.
void main()
{
#if defined(WIN32) || defined(WIN64)
#ifdef _DEBUG
#include <crtdbg.h>
 // _CRTDBG_ALLOC_MEM_DF ==> _CLIENT_BLOCK 에 메모리를 할당에 대해서 덤프
 // _CRTDBG_LEAK_CHECK_DF ==> 프로그램이 종료될 때 자동으로 _CrtDumpMemoryLeaks() 를 호출하여 메모리 누수시 덤프
 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
 // 해제 안되는 new 의 파일과 라인수를 파악한다.
 #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)

 // 메모리 누수시 블록숫자값(출력창의{1234})을 주면 메모리 공간을 확보하는 시점에 브레이크포인트가 걸린다.
 _CrtSetBreakAlloc(1359);
#endif
#endif
}

Visual C++ fatal error C1083

fatal error C1083 : Cannot open precompiled header file 'Debug/xxx.pch' No Such file or directory
또는
afx.h afxls_.h crtdbg.h xdebug xlocale 파일에 대해서 에러코드가 발생
하는 것은 컴파일시간을 줄이기 위해서 사용하는 미리 컴파일된 .pch(precompiled header)파일이 없어서 나타나는 문제이다.
해결 방법은 Project setting -> C/C++ -> PreCompiled Header -> Use precompiled header file 을 선택한다.
그리고 Rebuild All 하면 에러가 나타나지 않는다.
참고로 VC++ 에서는 MFC 의 자주 사용되는 소스들을 미리 컴파일 하여 사용하기 위해서 stdafx.h stdaf.cpp (Standard Application Frameworks) 를 생성하여 프로젝트에 포함시킨다.

Visual C++ msc version

[예] Visual C++ 6.0 에서 MFC 를 사용하여 작성한 프로젝트를 Visual C++ 2008 로 바꾼 후 컴파일할 때
WINVER not defined. Defaulting to 0x0600 (Windows Vista)
와 같은 메세지가 나오면 현재 프로젝트의 stdafx.h 파일의 맨 위 부분에 다음과 같이 정의 해 놓는다.

// bhyoon, 20080919
// Visual C++ 4.0 -> 1000
// Visual C++ 5.0 -> 1100
// Visual C++ 6.0 -> 1200
// Visual C++ 7.1(2003) -> 1310
// Visual C++ 8.0(2005) -> 1400
// Visual C++ 9.0(2008) -> 1500
#if _MSC_VER > 1400
// bhyoon, 20080919
// 0x0601 -> Windows 7
// 0x0600 -> Windows Vista
// 0x0502 -> Windows Server 2003
// 0x0501 -> Windows XP
// 0x0500 -> Windows 2000
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#endif

Visual C++ 동적으로 MFC 를 사용할 경우 필요한 DLL 파일들

MFC 를 동적으로 사용할 경우 필요한 dll 로, exe 와 같은 폴더나 시스템 폴더에 존재해야 한다.

// Visual C++ 6.0 DEBUG 경우
mfc42d.dll  mfco42d.dll msvcirtd.dll msvcrtd.dll

// Visual C++ 6.0 RELEASE 경우
mfc42.dll  mfco42.dll msvcirt.dll msvcrt.dll

// Visual C++ 9.0 (2008) DEBUG 경우
mfc90d.dll mfcm90d.dll msvcpm90d.dll msvcp90d.dll msvcr90d.dll

// Visual C++ 9.0 (2008) RELEASE 경우
mfc90.dll mfcm90.dll msvcpm90.dll msvcp90.dll msvcr90.dll

Visual C++ MFC Drag & Drop File

CTestApp::InitInstance()
{
    // 드래그 앤 드롭을 활성화 시킨다.
    m_pMainWnd->DragAcceptFiles(TRUE);
    return TRUE;
}

void CTestMainFrame::OnDropFiles(HDROP hDropInfo)
{
    // Index Value를 0xFFFFFFFF로 주면 드랍된 파일의 총 갯수가 리턴.
    int nFile = DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0);
    int i = 0;
    char szFilePath[256];
    if (nFile > 0)
    {
        for (i=0; i<nFile; i++)
        {
            // 파일 알아내기
            DragQueryFile(hDropInfo, i, szFilePath, 256);
        }
    }
    // 현재 드래그 앤 드롭된 파일의 경로를 알려준다.
    CTestDoc *pDoc = (CTestDoc*)GetActiveDocument();
    pDoc->OnFileOpenByDragAndDrop(szFilePath);

    CFrameWnd::OnDropFiles(hDropInfo);
    // 드롭된 정보 없애기
    DragFinish(hDropInfo);
}

Visual C++ MFC Class get pointer

// 다이얼로그 포인트 얻어 오기
CABCDialog *pdlgMain = (CABCDialog*) AfxGetMainWnd();

// 뷰나 도큐먼트의 포인트 얻어 오기
CMainWnd* pMain=(CMainWnd*)AfxGetMainWnd();
pMain->GetActiveDocument();
pMain->GetActiveView();

// 다이얼로그에서 다큐먼트 변수 읽어 올때.
pDoc = ((CMainFrame *)AfxGetApp()->GetMainWnd())->GetActiveDocument();
CMainFrame *pFrm = (CMainFrame *)AfxGetMainWnd();
CBasketBallEditView *pView = (CBasketBallEditView *)pFrm->GetActiveView();

// CTestApp에서
CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
CTestDoc* pDoc = (CTestDoc*)((CMainFrame*)AfxGetMainWnd())->GetActiveDocument();
CTestView* pView = (CTestView*)((CMainFrame*)AfxGetMainWnd())->GetActiveView();

// CMainFrame에서
CTestApp* pApp = (CTestApp*)AfxGetApp();
CTestDoc* pDoc = (CTestDoc*)GetActiveDocument();
CTestView* pView = (CTestView*)GetActiveView();

// CTestDoc에서
CTestApp* pApp = (CTestApp*)AfxGetApp();
CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
CTestView* pView = (CTestView*)((CMainFrame*)AfxGetMainWnd())->GetActiveView();

// CTestView에서
CTestApp* pApp = (CTestApp*)AfxGetApp();
CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
                  or (CMainFrame*)GetParent();
CTestDoc* pDoc = (CTestDoc*)((CMainFrame*)AfxGetMainWnd())->GetActiveDocument();
              or (CTestDoc*)GetDocument();

Visual C++ output debug string

// WinAPI Style 로 Debug 창에 출력하기
char msg[100];
int a = 100;
sprintf(msg, "Debug Testing... %d\n", a);
OutputDebugString(msg);

// MFC Style 로 Debug 창에 출력하기
int a = 100;
TRACE("Debug Testing... %d\n", a);