지난 2월 23일 날 진행되었던 2008년, Visual C++와 MFC의 변화 따라잡기 관련 글을 따라가다가
“Visual C++ 2008을 이용한 debugging과 Crash Dump Analysis 노하우 2008 (신경준 MVP / 안철수 연구소)” 세션 자료를 보게 되었습니다. 내용이 하도 좋아서, 교육을 진행한 신경준님의 블로그까지 방문하게 되었는데, 대박 좋은 글들을 많이 발견하게 되었습니다.
방문해 보시면 아시겠지만 Visual Studio 2008 에 대한 글뿐만 아니라, Visual Studio 2005 와 디버깅에 관련된 상당히 깊이 있는 내용까지…… 책에서 구하기 힘든 좋은 내용이 아주 많습니다.
(안랩은 여러 해 동안 저희 회사와 계약 중에 있어서 안랩 개발자 분도 몇 분 알고 있긴 한데 어쩌면 이름 정도는 들어 본 분일 수도 있을 것 같은 혼자 생각이 드네요. 어쨌든 신경준 님 좋은 자료 감사합니다 ~* ^^)
RSS 에 이전 글들을 읽어 보다가 작년 8월에 작성한 Visual Studio 2005 의 코드 분석 기능이라는 글을 발견했습니다.
Visual Studio 2005 에서 코드 분석 기능 사용해 보자
글에 적혀 있는 내용대로 저희 프로젝트에 해당 기능을 적용했더니 결과는 기대 이상이었습니다. 배열의 인수를 잘못 사용하는 치명적인 오류(하지만 컴파일 타임에 전혀 잡히지 않아서 문제를 발견하기가 쉽지 않습니다)를 기가 막히게 잡아줍니다.
코드 분석 기능은 아쉽게도 Visual Studio 2005 Team Edition 프로덕트에만 들어 있습니다. Visual Studio 2005 Pro 에는 해당 기능이 빠져 있어 이 기능을 활용해 볼 수가 없습니다.
코드 분석 설정 부분은 갱주니님 블로그에 상세히 적혀 있습니다. 사실 해야 할 일은 프로젝트 설정에서 “Enable Code Analysis For C/C++” 값만 “Yes(/analyze)”로 변경하고 빌드 하면 됩니다.
그런 다음 빌드 메뉴에 있는 “Run Code Analysis On Only 프로젝트” 를 실행시켜 컴파일 하면 기존에 경고 레벨 4까지 설정했을 때도 경고 한 줄 없었던 프로젝트가 100 개가 넘는 무수한 경고들을 뱉어 내기 시작했습니다. (경고가 안 나오신다면 그 동안 제대로 코딩 해 오셨다는 반증이겠지요)
Code Analysis를 작동시켜 발생한 경고들에는 아래와 같은 것들이 특히 많았습니다.
1. Buffer Overrun 경고 – strcpy 와 같은 목적 버퍼에 쉽게 넘쳐나 Buffer Overrun 문제가 발생할 수 있는 함수들은 무조건 경고가 나옵니다. Visual Studio 2005 로 가면서 strcpy_s 와 같은 버퍼 크기에 안전한 버전으로 꽤 많이 수정하고, 너무 많아 미처 수정하지 못한 곳에는 #pragma 로 경고 표시를 막고 있었는데 Code Analysis는 사정 봐 주지 않고 무조건 경고 처리합니다.
2. 배열 인덱스 체크 기능 – 아래 예와 같이 배열의 인덱스를 넘어가는 잘못된 인덱스 처리 부분을 컴파일 타임에 잡아 줍니다. 문법적 오류가 있는 것이 아니어서 주로 런타임시에 프로그램이 죽거나, 운이 좋아도 잘못된 처리로 이어지는 부분이라 위험성이 상당히 큰 버그인데, Code Analysis 는 너무 너무 훌륭하게도 이 부분을 확실하게 체크해서 발견 해 줍니다. 배열의 인자로 단순 상수가 아닌 변수를 사용하는 경우에도 해당 변수가 배열의 범위를 넘어 갈 수 있다는 경고를 잊지 않고 표시합니다.
long lData[10]; …. sValue.Format("%d",lData[10]); 위와 같은 코드를 만드면 아래와 같은 경고가 나옵니다. warning C6201: Index '10' is out of valid index range '0' to '9' for possibly stack allocated buffer 'lData’ |
3. 포인터에 대한 사용 주의 경고 – 인자로 넘어온 포인터나 new를 해서 만든 포인터를 다루는 프로그램에서 포인터가 유효한지 체크하지 않으면 경고가 나옵니다.
void CTest::DrawData(CDC * pDC) { ASSERT(pDC); pDC->FillSolidRect(rect,RGB(255,0,0)); ... } |
이 경우
if (pDC)
와 같은 포인터 체크로직을 넣어 NULL 포인터에 대한 대비를 하라고 알려줍니다. 사실 ASSERT(pDC) 는 디버깅 시에만 작동하기 때문에 경고대로 포인터를 한번 더 확인하는 것은 필수인데 개발 시 빠뜨린 곳이 상당히 많았습니다.
4. 중복된 변수 선언 – 하나의 함수 안에 같은 변수를 여러 번 선언하는 경우 잠재적인 데이터 처리 오류가 있다고 여기고 경고를 표출합니다. 이런 경우가 생각보다 상당히 많았습니다. 사람들이 보통 생각하는 임시 변수명이 몇 가지 없다 보니, 임시 변수들(i, j, pos, it 등)이 특히 중복으로 선언된 경우가 많았습니다.
CRect rcTmp; for (...) { CRect rcTmp; ... } |
5. 웬만한 묵시적인 Type Casting 들은 모두 경고 처리 됩니다.
6. sprintf 의 인자 개수 체크 – 가변형 인자를 입력으로 받는 경우 개발자의 실수로 인자가 적거나, 더 많거나 하는 경우가 가끔 있습니다. 인자가 모자라는 경우에는 비정상적인 프로그램 종료가 발생해서 이를 방지하기 위해 이전에 인자수가 정확한 지 체크하는 프로그램을 만들어 돌린 적이 있습니다. Code Analysis 에서는 자동으로 이러한 체크까지 완벽하게 해 줍니다. 다행히 오늘 확인해 본 프로젝트에서는 인자의 개수가 적은 경우는 발견하지 못했고, 여분으로(?) 몇 개 더 넣어 준 경우는 발견해서 수정했습니다.
이외에도 일반적인 컴파일 타임 경고나 오류에는 걸리지 않던 수많은 경고 사인을 찾아 줍니다. 상용 프로젝트를 관리하고 있는 제 입장에서는 이 중에 특히 ‘2’번과 같이 배열의 잘못된 인자로 접근하는 코드를 찾아주는 게 너무 고맙더군요. 프로그램을 눈으로 쫓아가도 사실 인덱스가 잘못되어 있는지 찾기 힘들고, 아주 꼼꼼하게 코드 리뷰하지 않을 경우 놓치기 쉬운 부분이었습니다. 특히 최초 개발 시에는 문제가 없었지만, 유지 보수를 하면서 배열의 크기와 인덱스 처리 부분 중 어느 한 부분만 수정하는 경우 주로 문제가 되었습니다. (물론 개발 시부터 배열에 대한 인덱스를 좀더 고민해서 사용했으면 문제 발생을 최소화 시킬 수 있긴 합니다)
Visual Studio 2005를 여러 해 사용하고 있었지만 이런 훌륭한 기능이 있는지 처음 알았네요. 해당 기능을 공개해 주신 갱주니님께 다시 한번 감사 드립니다. ^^;
'개발' 카테고리의 다른 글
XmlLite 을 이용한 메뉴 XML 로딩하기 (13) | 2008.04.16 |
---|---|
Visual Studio 2008 Profiler (7) | 2008.03.25 |
Source Line Counter (2) | 2008.03.19 |
마이너가 된 IE 8, 그리고 생각해 봐야 할 하위호환성 문제 (4) | 2008.03.07 |
유니코드로 개발하기(MFC 프로젝트) (14) | 2008.03.05 |
윈도우 비스타 어플리케이션 아이콘 (0) | 2008.02.29 |
댓글