디버깅을 위한 컴파일러 옵션 조정과 디버깅 활용.
작성자 : 정동헌
작성일 : 02.03.21
주요 내용
1. 디버깅 옵션의 의미.
2. 디버깅 런타임 라이브러리 사용시의 특징.
3. 릴리즈 모드에서 디버깅하기.
4. Watch 윈도우에서 "Register", "Pseudo-register"값 확인하기.
5. Watch 윈도우에서 변수값을 변수 타입을 구체적으로 정하여 값 확인하기.
Compiler options for finding Bugs
Compiler Options | 의미 |
/W4 | Warning Level을 최대로 하여 컴파일 ( 모든 빌드 타입에 가능 ) |
/D "_DEBUG" | Assetion, Trace 같은 디버깅용 코드가 컴파일시 포함되록 만든다. ( 디버그 빌드에서만 ) |
/GZ | 생성시에 초기화 되지 않는 변수를 특정 값으로 채워 놓아서 흔히 디버그에서는 나타나지 않고 릴리즈 빌드에서 나타나는 에러를 사전에 검사할 수 있게 하여 디버그에 도움이 되게 함. ( 디버그 빌드에서만 ) |
/Od | 최적화하지 않는다. 코드를 디버그에 적합하게 만든다. ( 디버그 빌드에서만 ) |
/GF | 실행 파일에 들어갈 스트링이 중복될 경우 이를 제거, 공동으로 사용되는 이 스트링이 할당된 메모리를 읽기 전용으로 설정하여 우발적인 메모리 쓰임으로 부터 보호함.
char *s = "This is a character buffer"; char *t = "This is a character buffer";
위와 같은 경우 같은 스트링이므로 스트링을 서로 공유 함. ( 릴리즈 모드에서 명시적으로 사용시 ) |
/Gf | 실행파일에 들어갈 스트링을 공유하는 것은 위와 같으나 우발적인 메모리 쓰임으로 부터 보호 하지 않음. |
/ZI | 디버깅 심벌용 프로그램 데이터베이스를 만듬. 디버그로 실행시에 코드를 편집후 연속해서 디버깅이 가능하게 정보를 관리. ( 디버그 빌드에서만 ) |
/Zi | 디버깅 심벌용 프로그램 데이터베이스를 만듬. ( 릴리즈 빌드에서만 ) |
Compiler options for a debug build
Linker Options | 의미 |
/MDd, /MLd, /MTd | 디버그 실시간 라이브러리 사용. |
/Od | 최적화하지 않는다. |
/D "_DEBUG" | 디버그용 코드가 컴파일 되게 한다. |
/ZI | 편집, 연속 디버깅이 가능하게 디버그용 데이터배이스를 만듬. |
/GZ | 디버그 빌드에서의 흔한 실수로 릴리즈에서 나타나는 에러를 디버그모드에서 검출. |
/Gm | 빌드 시간을 재빌드시에 감축시키기. |
Compiler options for a release build
Linker Options | 의미 |
/MD, /ML, /MT | 릴리즈 실시간 라이브러리 사용. |
/O1 or /O2 | 속도 최적화나 사이즈 작게 최적화 같은 것을 가능하게. |
/D "NDEBUG" | 디버그용 코드가 컴파일되지 않게 함. |
/GF | 중복된 문자열을 방지, 읽기 전용으로 데이터를 보호함. |
디버그 런타임 라이브러리 사용.
- 디버그 런타임 라이브러리는 메모리 할당을 추적하고 메모리 누수를 점검한다.
- 새로이 메모리 할당되어 초기화 되지 않은 데이터에 "0XCD"의 바이트 패턴으로 써놓는다.
- 메모리 할당이 해제될 경우에 “0XDD"의 바이트 패턴으로 표시를 하여 해제된 메모리라고 알 수 있도록 표시한다.
- 할당된 메모리 버퍼의 양쪽 끝 부분에 DWORD 사이즈로 “0XFD"의 바이트 패턴으로 표시를 해둬서 memory overwrite나 memory underwrite를 체크할 수 있게 한다. ( 즉 디버그 모드에서는 메모리 할당시에 양쪽에 각각 DWORD의 공간이 마킹하기 위해서 추가적으로 할당이 된다. )
- 메모리 할당시 소스코드 상에서의 위치를 알아 내는데 도움이 되도록 소스코드의 파일 이름과 해당줄을 추적을 위해서 넣어 놓는다.
디버그 빌드에서 릴리즈 빌드 에러를 검출하기.
“/GZ" 컴파일러 옵션을 삽입시,
1. 초기화되지 않은 포인터에 대한 접근 위반을 검출하기 위해 "0XCC“ 패턴으로 자동적으로 변수를 초기화 함.
2. 비주얼 C++은 디버그 모드에서는 모든 변수를 자동적으로 0로 초기화하고 릴리즈 모드에서는 그렇지 않는다. 이것은 컴파일러가 하는 일중에 가장 허접한 것이다. 이것으로 릴리즈 모드에서 예상하지 못한 에러를 만날 수 있다. 그러나 “/GZ"라는 컴파일 옵션을 주면 모든 변수를 ”0XCC"로 초기화 함으로써 이를 방지할 수 있다.
릴리즈 모드에서 디버깅하기
1. “Project/Settings/"을 선택하여 프로젝트 세팅 다이알로그를 띠운다.
2. ”C/C++“ 탭에서 ”General" 카테고리를 선택해서 "Optimizations"을 “Disable(Debug)"로 선택하고 “Debug info" 항목을 ”Program Database“로 바꾼다.
3. "Link" 탭에서 “Debug" 카테고리를 선택하면 ”Debug info" 항목이 있는데 여기서 "Microsoft format"을 선택한다.
4. “Link" 탭에있는 ”Project Options" 박스에 들어 있는 내용의 맨 끝에 "/OPT:REF"를 추가 한다.
5, 반드시 “Rebuild All"로 제 컴파일을 한다.
Note : Vs 7.0 (.Net )에서의 설정 방법.. (한글판 기준)
1. C/C++에서 일반 항목중에서, 디버깅 정보 형식을 “사용안함"에서 “편집하며 계속하기를 위한 프로그램 데이터베이스(/ZI)"로 변경.
2. C/C++에서 최적화 항목중에서, 최적화를 “속도최대화(/O2)”에서 “사용안함(/Od)"로 변경.
3. C/C++에서 최적화 항목중에서, 인라인 함수 확장을 “__inline(/Ob1)" 에서 사용 안함으로 변경.
4. 링커에서 디버그 항목중에서, 디버그 정보 생성을 “아니요”에서 “예(/DEBUG)"로 변경.
** 디버깅 후에는 꼭 설정을 되돌려놔야 한다.
Registers And Pseudo-registers
Register값은 “Registers" 윈도우에서 확인이 가능하지만 단순하고 값만을 알수 있다. 이 값들을 ”Address(Watch)" 박스에서도 확인이 가능하며 여러 부가 기능과 같이 쓸수 있다.
예를 들어 EAX의 값을 확인 해볼려고 하면 Watch 항목에 “@EAX"혹은 ”@eax"와 같이 대소문자를 구분하지 않고 넣으면 이 래지스터의 값을 확인 할 수 있다.
또한 Pseudo-register"의 값또한 확인 할수 있는데. "@ERR"의 Pseudo-register 값은 매우 유용하게 사용할 수 있는데 이 값이 GetLastError의 값을 나타내기 때문이다. 만약 “@ERR,hr"이라고 입력한다면 Win32의 에러코드에 해당하는 택스트를 보여 줄것이다.
Pseudo-register | 의미 |
@ERR | GetLastError API로 알 수 있는 가장 최근에 반환된 에러 코드를 보여줌 |
@CLK | 누적시간(MicroSecond)을 보여줌. |
@TIB | TIB의 주소를 보여줌. |
Pseudo-registers that the Watch window supports
Register | 사용(용도) |
@EAX | 일반 용도, 함수의 return 값으로 사용 |
@EBX | 일반 용도 |
@ECX | 일반 용도, 오브젝트의 this 포인터로 사용. |
@EDX | 일반 용도, 64비트의 return값의 경우 상위 값의 반환에 사용. |
@ESI | 메모리 이동과 비교 연산시의 원본 메모리 |
@EDI | 메모리 이동과 비교 연산시에 대상 메모리 |
@EIP | 명령 포인터 ( 코드의 현제 위치 ) |
@ESP | 스텍 포인터 ( 스텍의 현제 위치 ) |
@EBP | 스텍 배이스 포인터 ( 현제 스텍 프레임의 바닥 ) |
@EFL | 비교나 수학 연산을 위한 플래그 비트 |
@CS | Code segment |
@SS | Stack segment |
@DS | Data segment |
@ES | Extra segment |
@FS | Another extra segment, used to point to the TIB |
@GS | Yet another extra segment |
Watch Window Formatting Symbols
이 윈도우는 변수의 값을 볼수 있게 해주는데, 값을 십진수나 16진수로서 확인할 수 있다. 16진수는 팝업 메뉴에서 “Hexadecimal Display"를 선택하면 볼수 있다. 이 이외에도 여러 가지 옵션을 주어서 사용할 수 있는데 이들은 Watch Window에 등록되는 변수명 뒤에 ","를 삽입하고 그뒤에 옵션을 주어 사용할 수 있다.
Symbol | Format | Example | Output |
d, i | 부호있는 10진 정수 | -42,d | -42 |
u | 부호없는 10진 정수 | 42,u | 42 |
o | 부호없는 8진 정수 | 42,o | 052 |
x | 16진 정수 | 42,x | 0x0000002a |
X | 16진 정수 | 42,X | 0x0000002A |
h | Short prefix for d,i,u,o,x | 42,hx | 0x002a |
f | 실수 | 1.5,f | 1.500000 |
e | 부호 있는 과학용 표기 | 1.5,e | 1.500000e+000 |
g | Compact float | 1.5,g | 1.5 |
c | 문자 | 42,c | '*' |
s | ANSI 문자열 | "bugs",s | "bugs" |
su | UNICODE 문자열 | "bugs",su | "bugs" |
st | 기본 문자열형 ( s, su중에서 ) | "bugs",st | "bugs" |
hr | HRESULT, Win32 error code | 0x06,hr | The handle is invaid |
wm | Wndows message number | 0x01,wm | WM_CREATE |
[digits] | 배열 | s,5 | 배열 5개의 항목 표시 |
'Tip & Tech > VS 프로젝트 설정' 카테고리의 다른 글
Visual Studio 도구상자 아이콘 깨짐현상 해결법(VS IDE 리셋) (2) | 2010.11.25 |
---|---|
릴리즈 모드로 build 된 프로그램의 디버깅 (0) | 2010.10.14 |
브레이크 포인트가 비활성화 될때 - '고급편 2' (0) | 2010.09.06 |
브레이크 포인트가 비활성화 될때 - '고급편' (0) | 2010.09.06 |
릴리즈 모드로 디버깅 하는 방법(2) (0) | 2010.09.03 |