Windows/MFC
Debuging 디버깅 방법
aucd29
2013. 10. 2. 17:55
까막입니다...
디버깅이라... 쩝~~ 비씨중에서 가장 어려운길로 접어 드셨군여.. --;;;
(올린이 : 디버깅이 젤루 어렵다는 말씀이신거 같습니다.)
프로그램이 커지면 커질 수록 디버깅의 비중은 늘고 늘어 어느새 프로그램의
반을 차지해 버립니다...
(올린이 : 저는 이미 전부가 되었습니다.)
상용화 프로그램을 개발할 경우 정말 상상도 못한 별의별 에러가 다 나옵니다.
95는 않되구, 98은 되구, 2000은 않되구 NT는 되구... 에구구....
익스프롤러를 제어하는 부분이라면... 아예 버전에 따라 기상천외한 에러가
발생합니다...
(올린이 : 저는 제 프로그램이 CIH바이러스를 능가하는 바이러스인줄 알았습니다.)
이러한 많은 문제에 부딧혀 갈 때 어떻게 하면... 에러를 쉽게 찾을 수 있을까?
이러한 생각속에 태어나는게 자신만의 디버깅 방법입니다...
(올린이 : 꼭 참고하시기를)
일반적으로 가장 많이 사용하는 것이 TRACE()문과 ASSERT()문입니다.
1. TRACE()는 어떤 연속적으로 변화하는 값들을 추적할 때 일일이 하나씩 Variable
창에 나타나는 값을 확인하는 수고를 덜어 줍니다...
문장을 출력할 때 어떤 함수의 어떤 변수라는 값도 함께 적어 주면...
한 눈에 결과를 알아 볼 수 있져...
TRACE("요기다 어떤 변수의 값들을 적어 주면 되져.. 보통 CString의 Format를 이용)
하지만.. 트레이스 문을 너무 많이 찍으면 시스템이 죽을 수도 있으므로 조심.한번에
루프안에다 집어 넣어서 한 10만개 정도 찍어보니 죽어 버려여...뭐가? 컴터가...
2. ASSERT()는 어떠한 윈도우나 메모리, 핸들의 값이 유효한지를 검사합니다.
여기다 어떤 값들을 넣어줄 때 좋은점... 핸들등에 문제가 있어 프로그램이 종료
할때 어떤 파일의 몇번째 줄이라는 에러 메세지를 출력해줍니다.
그러므로 어디서 에러가 낮는 지 금방 찾을 수 가 있져...
3. GetLastError() 함수를 써서 어떤 루틴이나 클래스의 처리과정에서 함수들의
이상한 리턴 값등으로 사람 머리아프게 만드는 에러의 정확한(?) 원인을 알아보는데
사용하는 함수 입니다... 보통 어떤 함수의 리턴 값이 숫자로 나오면..황당하져..
이 함수는 시스템의 에러메세지 큐에 쌓여 있는 에러 메시지중에서 가장 마지막의
에러 메세지를 가져옵니다..
그러므로, 함수의 사용이 몇개의 에러가 난후에 사용된다면... 원치 않는 결과를
가져올 수도 있습니다.. --;;;
4. try ~ catch 블럭을 이용한 예외상황 처리하기가 있습니다....
어떠한 함수들의 실행을 이 블럭 안에서 실행하여.. 정상적인 종료이면..
퉁과하고 에러가 발생하면... catch 블럭으로 들어가서 익셉션핸들러에 의해
에러 레포트를 메시지 박스로 출력해 줍니다...
5. 또 간단한 예외상황 처리에서 항상 if블록에 else 블록을 넣어서 그 외의 값이
나올 때 예외상황이 발생하였음을 메시지 박스로 알려 주어도 좋습니다.
switch()문도 마찬가지이구여...
6. 그외에 함수들의 리스트를 확인하면.. 앞에 접두어로 Is라고 붙은 함수들이
상당히 아주 많습니다..
이러한 함수들은 대부분 어떤 특정값들이 유효한가를 판단하는 함수들입니다.
이러한 함수들만 잘 이용하여도 원하지 않는 결과를 가지고 작업하는 일은
상당히 줄어 들지여... 보통 에러가 날 때 원치 않는 결과 값을 사용하여 에러나는
경우가 가장 열받는 경우 입니다... 어느 순간에 갑자기 값이 바껴서 갑자기(?)
컴터가 켁하구 죽으면 정말 열받습니다.
그러므로, 주요한 루틴으로 진입할 때 이러한 에러처리 루틴이나 함수들을 넣어
주면.. 사전에 이러한 에러를 찾을 수 가 있지여...
7. 엄청난 계산을 하는 루틴들이 가끔 있습니다... 이러한 루틴은 보통 루프에서
돌아가는 변수를 첵크하여...현재 진행 상황을 살펴 볼 수가 있는데...
타이머를 써서 괜히 속도 늦추는거 아니냐고 따질 수도 있지만..
전 몇 분이상을 도는 루틴에는 항상 타이머를 달아 놓습니다..
그래서 0 부터 count까지를 100으로 가정하고 이 값들을 첵크합니다..
프로그래스로 보여주는것도 괜찬아여... 에궁.. 이건 쩜 부하가 걸려여..
화면 아무데나 귀퉁이에 그냥 숫자로 써주어도 좋구여... 이값이 멈추거나...
아니면...100을 넘어가면... 환장하는 겁니다... 에러... 삐요 삐요~~~
이런거 없이 무한 루푸에 빠졌는데도 끈질긴 집념을 가지고 지켜보시는 대단한
분들이 있습니다.. 정말 대단한 정신력입니다..
그러고나서, 하는 말이.. 쩜 너무 데이터를 많이 넣었나? 휴~~~~
보통 메모리가 요즘 64M져... 시스템이 윈98정도라 가정해도... 32M정도만이라고
해도.. 정말 엄청난 크기의 배열을 잡을 수 있습니다...
그러므로 엄청난(?) 양의 데이터를 계산하는 루틴에는 항상 타이머와...
메세지 큐를 첵크하는 translatemessage()~dispatchmessage()블럭을 넣어 주면..
메세지로 돌아가지여... 요건 단일 스레드에서 사용하는 방법이구여..
멀티 스레드라면... 타이머 만으로도 충분합니다.
그리고, 외부에서 이 루프를 죽일(강제로 중단할) 수 있는 방법도 함께 만드러 놓으면
첨에 만들기는 힘들지만... 한 번 돌리고 에러나면 메모리 풀이라서... 다시
부팅하는 수고를 덜을 수 있습니다..
8. 특히 네트워크를 이용한 소켓 프로그램이나.. 인터넷 세션, 에프티피 세션등을
이용하여 외부에 접속을 하거나 데이터를 가져올 때... --;;;
요런 것들은 무한 루푸 빠지면.. Ctrl+Art+Del로 죽일 수 있지만...
TimeOut 첵크 루틴 하나만 넣어놔도... 이러한 수고를 줄 일 수 있습니다..
어떤 서버에 접속할 때 접속 신호를 보내고 1분이내에 응답이 없으면...
서버가 죽었던지 네트워크 트레픽이든지.... 중단하고 원래 하던일을 해야겠져..
근데.. 이것도 끈질기게 지켜보시는 분들 있습니다..
요즘 소켓 클래스들을 보면.. 보통 Connect에 타임아웃 첵크 루틴이 내부적으로
들어 있는 것도 많던데.. 글고 다 멀티 스레드 방식이라(내부적으로) 보통..
자동으로 연결을 해제시켜 줍니다..
항상 무한 루프나 어떤 값을 기다리는 이러한 시간을 무진장 소모하는 루틴에는
항상 타이머를 답시다...^^;;;
9. 그 외에도 수많은 방법이 있겠지만... 그냥 프로그램적으로 사용하는 것은
이 정도 뿐입니다.. 전 아직 디버깅에 익숙하지 않아서 여기 까지만 적어 봅니다..
10. 참고로 디버깅에서 사용되는 간단한 단축키 몇 개를 초보자 님들을 위하여
적어 봅니다.
F5 : 브레이크 포인터를 만날 때 까지 한꺼번에 슝하고 달린다...
F9 : 브레이크 포인터를 걸고 지운다.
F10 : 한줄 씩 건너 다닌다. 함수 가 있으면.. 그냥 한줄로 이해하고 그냥 넘어간다.
F11 : 이건 그냥 한줄 씩 가다가 함수나 클래스를 만나면.. 내부로 들어간다.
F12 : 현재 커서 가 있는 곳 까지 건너 댕긴다...
shift + F5 : 디버깅 종료.
shift + F11 : F11로 들어간 루틴을 끝까지 추적하지않고 원래 가던길로 나온다.
ctrl + F9 : 브레이크 포인터를 인에이블, 디스에이블 시킨다.
shift + ctrl + F9 : 여기 저기 걸어 놓은 브레이크 포인터를 몽땅 지운다..
ctrl + F2 : 위치 지정 마크를 단다...
F2 : 위치 지정 마크가 붙은곳을 날라 다닌다. (하나의 파일내에서)
ctrl + TAB : 방금전에 작업한 파일을 연다...
더 많은 거 같은데 잘 생각이 않나네여..
그럼 즐거운 하루 되세여...
글고, 혹시나 이글을 읽으시는 고수님들이 계시면..
노하우를 쩜 적어 주세여...
디버깅이라... 쩝~~ 비씨중에서 가장 어려운길로 접어 드셨군여.. --;;;
(올린이 : 디버깅이 젤루 어렵다는 말씀이신거 같습니다.)
프로그램이 커지면 커질 수록 디버깅의 비중은 늘고 늘어 어느새 프로그램의
반을 차지해 버립니다...
(올린이 : 저는 이미 전부가 되었습니다.)
상용화 프로그램을 개발할 경우 정말 상상도 못한 별의별 에러가 다 나옵니다.
95는 않되구, 98은 되구, 2000은 않되구 NT는 되구... 에구구....
익스프롤러를 제어하는 부분이라면... 아예 버전에 따라 기상천외한 에러가
발생합니다...
(올린이 : 저는 제 프로그램이 CIH바이러스를 능가하는 바이러스인줄 알았습니다.)
이러한 많은 문제에 부딧혀 갈 때 어떻게 하면... 에러를 쉽게 찾을 수 있을까?
이러한 생각속에 태어나는게 자신만의 디버깅 방법입니다...
(올린이 : 꼭 참고하시기를)
일반적으로 가장 많이 사용하는 것이 TRACE()문과 ASSERT()문입니다.
1. TRACE()는 어떤 연속적으로 변화하는 값들을 추적할 때 일일이 하나씩 Variable
창에 나타나는 값을 확인하는 수고를 덜어 줍니다...
문장을 출력할 때 어떤 함수의 어떤 변수라는 값도 함께 적어 주면...
한 눈에 결과를 알아 볼 수 있져...
TRACE("요기다 어떤 변수의 값들을 적어 주면 되져.. 보통 CString의 Format를 이용)
하지만.. 트레이스 문을 너무 많이 찍으면 시스템이 죽을 수도 있으므로 조심.한번에
루프안에다 집어 넣어서 한 10만개 정도 찍어보니 죽어 버려여...뭐가? 컴터가...
2. ASSERT()는 어떠한 윈도우나 메모리, 핸들의 값이 유효한지를 검사합니다.
여기다 어떤 값들을 넣어줄 때 좋은점... 핸들등에 문제가 있어 프로그램이 종료
할때 어떤 파일의 몇번째 줄이라는 에러 메세지를 출력해줍니다.
그러므로 어디서 에러가 낮는 지 금방 찾을 수 가 있져...
3. GetLastError() 함수를 써서 어떤 루틴이나 클래스의 처리과정에서 함수들의
이상한 리턴 값등으로 사람 머리아프게 만드는 에러의 정확한(?) 원인을 알아보는데
사용하는 함수 입니다... 보통 어떤 함수의 리턴 값이 숫자로 나오면..황당하져..
이 함수는 시스템의 에러메세지 큐에 쌓여 있는 에러 메시지중에서 가장 마지막의
에러 메세지를 가져옵니다..
그러므로, 함수의 사용이 몇개의 에러가 난후에 사용된다면... 원치 않는 결과를
가져올 수도 있습니다.. --;;;
4. try ~ catch 블럭을 이용한 예외상황 처리하기가 있습니다....
어떠한 함수들의 실행을 이 블럭 안에서 실행하여.. 정상적인 종료이면..
퉁과하고 에러가 발생하면... catch 블럭으로 들어가서 익셉션핸들러에 의해
에러 레포트를 메시지 박스로 출력해 줍니다...
5. 또 간단한 예외상황 처리에서 항상 if블록에 else 블록을 넣어서 그 외의 값이
나올 때 예외상황이 발생하였음을 메시지 박스로 알려 주어도 좋습니다.
switch()문도 마찬가지이구여...
6. 그외에 함수들의 리스트를 확인하면.. 앞에 접두어로 Is라고 붙은 함수들이
상당히 아주 많습니다..
이러한 함수들은 대부분 어떤 특정값들이 유효한가를 판단하는 함수들입니다.
이러한 함수들만 잘 이용하여도 원하지 않는 결과를 가지고 작업하는 일은
상당히 줄어 들지여... 보통 에러가 날 때 원치 않는 결과 값을 사용하여 에러나는
경우가 가장 열받는 경우 입니다... 어느 순간에 갑자기 값이 바껴서 갑자기(?)
컴터가 켁하구 죽으면 정말 열받습니다.
그러므로, 주요한 루틴으로 진입할 때 이러한 에러처리 루틴이나 함수들을 넣어
주면.. 사전에 이러한 에러를 찾을 수 가 있지여...
7. 엄청난 계산을 하는 루틴들이 가끔 있습니다... 이러한 루틴은 보통 루프에서
돌아가는 변수를 첵크하여...현재 진행 상황을 살펴 볼 수가 있는데...
타이머를 써서 괜히 속도 늦추는거 아니냐고 따질 수도 있지만..
전 몇 분이상을 도는 루틴에는 항상 타이머를 달아 놓습니다..
그래서 0 부터 count까지를 100으로 가정하고 이 값들을 첵크합니다..
프로그래스로 보여주는것도 괜찬아여... 에궁.. 이건 쩜 부하가 걸려여..
화면 아무데나 귀퉁이에 그냥 숫자로 써주어도 좋구여... 이값이 멈추거나...
아니면...100을 넘어가면... 환장하는 겁니다... 에러... 삐요 삐요~~~
이런거 없이 무한 루푸에 빠졌는데도 끈질긴 집념을 가지고 지켜보시는 대단한
분들이 있습니다.. 정말 대단한 정신력입니다..
그러고나서, 하는 말이.. 쩜 너무 데이터를 많이 넣었나? 휴~~~~
보통 메모리가 요즘 64M져... 시스템이 윈98정도라 가정해도... 32M정도만이라고
해도.. 정말 엄청난 크기의 배열을 잡을 수 있습니다...
그러므로 엄청난(?) 양의 데이터를 계산하는 루틴에는 항상 타이머와...
메세지 큐를 첵크하는 translatemessage()~dispatchmessage()블럭을 넣어 주면..
메세지로 돌아가지여... 요건 단일 스레드에서 사용하는 방법이구여..
멀티 스레드라면... 타이머 만으로도 충분합니다.
그리고, 외부에서 이 루프를 죽일(강제로 중단할) 수 있는 방법도 함께 만드러 놓으면
첨에 만들기는 힘들지만... 한 번 돌리고 에러나면 메모리 풀이라서... 다시
부팅하는 수고를 덜을 수 있습니다..
8. 특히 네트워크를 이용한 소켓 프로그램이나.. 인터넷 세션, 에프티피 세션등을
이용하여 외부에 접속을 하거나 데이터를 가져올 때... --;;;
요런 것들은 무한 루푸 빠지면.. Ctrl+Art+Del로 죽일 수 있지만...
TimeOut 첵크 루틴 하나만 넣어놔도... 이러한 수고를 줄 일 수 있습니다..
어떤 서버에 접속할 때 접속 신호를 보내고 1분이내에 응답이 없으면...
서버가 죽었던지 네트워크 트레픽이든지.... 중단하고 원래 하던일을 해야겠져..
근데.. 이것도 끈질기게 지켜보시는 분들 있습니다..
요즘 소켓 클래스들을 보면.. 보통 Connect에 타임아웃 첵크 루틴이 내부적으로
들어 있는 것도 많던데.. 글고 다 멀티 스레드 방식이라(내부적으로) 보통..
자동으로 연결을 해제시켜 줍니다..
항상 무한 루프나 어떤 값을 기다리는 이러한 시간을 무진장 소모하는 루틴에는
항상 타이머를 답시다...^^;;;
9. 그 외에도 수많은 방법이 있겠지만... 그냥 프로그램적으로 사용하는 것은
이 정도 뿐입니다.. 전 아직 디버깅에 익숙하지 않아서 여기 까지만 적어 봅니다..
10. 참고로 디버깅에서 사용되는 간단한 단축키 몇 개를 초보자 님들을 위하여
적어 봅니다.
F5 : 브레이크 포인터를 만날 때 까지 한꺼번에 슝하고 달린다...
F9 : 브레이크 포인터를 걸고 지운다.
F10 : 한줄 씩 건너 다닌다. 함수 가 있으면.. 그냥 한줄로 이해하고 그냥 넘어간다.
F11 : 이건 그냥 한줄 씩 가다가 함수나 클래스를 만나면.. 내부로 들어간다.
F12 : 현재 커서 가 있는 곳 까지 건너 댕긴다...
shift + F5 : 디버깅 종료.
shift + F11 : F11로 들어간 루틴을 끝까지 추적하지않고 원래 가던길로 나온다.
ctrl + F9 : 브레이크 포인터를 인에이블, 디스에이블 시킨다.
shift + ctrl + F9 : 여기 저기 걸어 놓은 브레이크 포인터를 몽땅 지운다..
ctrl + F2 : 위치 지정 마크를 단다...
F2 : 위치 지정 마크가 붙은곳을 날라 다닌다. (하나의 파일내에서)
ctrl + TAB : 방금전에 작업한 파일을 연다...
더 많은 거 같은데 잘 생각이 않나네여..
그럼 즐거운 하루 되세여...
글고, 혹시나 이글을 읽으시는 고수님들이 계시면..
노하우를 쩜 적어 주세여...