DCRT

Debug C Runtime 클래스를 이용하면 라이브러리가 알아서 동적할당되는 메모리를 역추적하여 누수되는 메모리를 가늠하는 것이 가능하다.
자기가 짠 프로그램으로 돌려보고 누수 여부를 판단하기에 좋을 것이다.

~cpp _crtDbgFlag

_CRTDBG_ALLOC_MEM_DF 디버그 할당 활성화. free store 상태 추적
_CRTDBG_DELAY_FREE_MEM_DF 메모리를 delete에 의해 해지 되지 않도록함. 메모리 부족상황하에 발생하는 일을 알 수 잇음
_CRTDBG_CHECK_ALWAYS_DF _CrtCheckMemory() 함수를 모든 new, delete 함수에 대해서 자동 호출 되도록 지정한다.
이 함수는 할당된 공간의 유효성을 지속적으로 체크한다. 즉 domainerror나 기타 메모리 access에 관한 부분을 검사한다. 대신 오버헤드가 상당하다. 그러나 그만큼 디버깅의 효율성을 높여줄 수 있다.
_CRTDBG_CHECK_CRT_DF 내부적으로 사용되는 메모리가 디버그작업을 하는 동안 추적된다.
_CRTDBG_LEAK_CHECK_DF 프로그램이 종료되는 시점에서 _CrtDumpMemoryLeaks()를 호출. 메모리 해제에 실패한 경우 그 정보를 얻을 수 있다.
_CRTDBG_ALLOC_MEM_DF 는 기본적으로 on, 기타 플래그는 디폴트 off이므로 bitwise 연산자를 이용해서 적절하게 플래그를 설정해야한다.

~cpp 
int flas = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
flag |= _CRTDBG_LEAK_CHECK_DF;  // 플래그 on
flag &= !_CRTDBG_LEAK_CHECK_DF;  // 플래그 off
_CrtSetDbgFlag(flag);

Code

~cpp 
//this define must occur before any headers are included.
//반드시 include 전처리기의 앞부분에 선언되어야함.
#define _CRTDBG_MAP_ALLOC

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>

// include crtdbg.h after all other headers.
// 전처리 문장이 끝난뒤에 include
#include <crtdbg.h>

int main(int argc, char *argv[]) {
	//turn on the full heap checking
	//DCRT의 오버헤드가 상당하기 때문에 기본옵션이 꺼져있다고 한다. 따라서 다음과 같이 옵션을 활성화 하는 작업이 필요
	_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF	|
					_CRTDBG_CHECK_ALWAYS_DF	|
					_CRTDBG_DELAY_FREE_MEM_DF	|
					_CRTDBG_LEAK_CHECK_DF	);

	//Allocate some more memory.
	TCHAR* pNew = new TCHAR[200];
	TCHAR* pNew2 = new TCHAR[200];
	TCHAR* pMemLeak = (TCHAR*)malloc (100);

	_tcscpy( pNew, _T("New'd memory...") );
	_tcscpy( pNew2, _T("more New'd memory...") );
	_tcscpy( pMemLeak, _T("Malloc'd memory...") );

	return EXIT_SUCCESS;
}
MFC에서는 기본적으로 로드하지만 콘솔에서는 사용자가 직접 지정을 해줘야 로드한다.

CRT 기타 함수

CRT의 기본 함수들의 출력은 디버그 메시지 윈도우이다. 이를 변경하기위해서는 _CrtSetReportMode()라는 함수를 이용해서 출력에대한 일반 목적지를 지정하고, _CrtSetReportFile()를 이용해서 특별한 스트림 목적지를 설정해야한다.
~cpp int _CrtSetReportMode(int reportType, int reportMode);

reportType
_CRT_WARN 경고 메시지 예)memory leak
_CRT_ERROR 복구불가한 치명적 에러
_CRT_ASSERT assertion 출력(assert() 출력이 아니다)
crtdbg.h는 ASSERT, ASSERTE라는 메크로 함수를 생성한다. 둘의 차이점은 ASSERTE는 assertion 표현을 보고하고, 다른 것은 하지 않는 다는 것이다.

reportMode
_CRTDBG_MODE_DEBUG 디버그 윈도우 안에서 보게될 디버그 문자열에 출력을 전달
_CRTDBG_MODE_FILE output stream
_CRTDBG_MODE_WNDW 메시지 박스
_CRTDBG_REPORT_MODE 현재의 리포트 모드를 리턴한다.
다중 목적지 지정은 flag 설정과 마찬가지로 | 연산자를 통해서 가능하다.


~cpp _HFILE _CrtSetReportFile(int reportType, _HFILE reportFile);
두번째 인수는 파일 스트림의 _HFILE 형식의 포인터이거나 다음의 식별자들 중의 하나이다.
_CRTDBG_FILE_STDERR 표준 에러 스트림으로 전달
_CRTDBG_FILE_STDOUT 표준 출력 스트림으로 전달
_CRTDBG_REPORT_FILE 현재의 목적지를 리턴한다.

output in debug console (vc++6)

dcrt_output_debug_console.jpg

after

대체로 클래스에서의 메모리 유출은 동적 멤버 변수들이 만들어졌을 때 해야하는 '삼의 법칙'을 지키지 않는데서 비롯되는 경우가 많다.
동적 멤버변수를 사용하는 경우에는 대입, 할당 생성자, 소멸자를 반드시 만들어야한다.
참조) The rule of Three(http://zeropage.org/wiki/AcceleratedC_2b_2b_2fChapter11#line287)

related

MSDN(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/_core_c_run2dtime_library_debugging_support.asp)

after

DCRT를 켜고 끄는 것에 따라서 프로그램의 수행속도의 차이가 상당하다. STL때문인지도 모르겠지만. - eternalbleu

Retrieved from http://wiki.zeropage.org/wiki.php/DebuggingSeminar_2005/DebugCRT
last modified 2021-02-07 05:23:06