U E D R , A S I H C RSS

Debugging Seminar_2005/DebugCRT

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

related

after

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

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:23:06
Processing time 0.0247 sec