jobGuid 꽃미남 프로그래머 "Pope Kim"님의 이론이나 수학에 치우치지 않고 실무에 곧바로 쓸 수 있는 실용적인 셰이더 프로그래밍 입문서 #겁나친절 jobGuid "1판의내용"에 "새로바뀐북미게임업계분위기"와 "비자관련정보", "1판을 기반으로 북미취업에 성공하신 분들의 생생한 경험담"을 담았습니다. 3ds Max를 사용해서 게임용 3D 캐릭터를 셋업하는 방법
이를 위해 오랜 실무를 경험해 온 저자의 고급 노하우들이 공개
위 내용은 GameDevForever의 저자분들의 홍보를 위하여 운영진 자체적으로 올린 광고이며 일체의 수익이 없습니다.(밥좀사줘요~)
Posted by 김포프
컴파일 경고(warning) 얼마나 신경쓰세요? 현재 작업중인 코드베이스를 컴파일하면 경고가 몇개나 나오나요? 하나라도 있다면 반드시 다 고치세요. 구차한 변명따윈 필요없습니다. 하나도 안나오게 다 고치세요. 왜인지는 얼마전에 있던 제 경험담을 통해 아주 짧게 주저리주저리 설명드립니다.

며칠 전에 발견한 컴파일 경고 하나
현재 마무리를 도와주고 있는 콘솔게임을 PS3용으로 컴파일하다(즉 g++을 사용하면) 운좋게(왜 운좋은건지는 나중에 설명) 다음과 같은 컴파일 경고를 봤습니다.

1>..\..\src\monster.cpp(2814): warning : unused variable 'temp'


보통 때 같으면 무시하겠는데(왜 무시하는지도 나중에 설명.. 원래는 절대 무시하면 안됨) 그날 따라 무슨 신내림을 받았던지...

'응? 이놈이 뭐지? 궁금한걸?'

이란 생각이 더블클릭을 해서 소스코드를 봤지요. 

bool swapped = false;
if( dist1 > dist2 )
{
  swapped = true;
  float temp = dist1;
  dist1 = dist2;
  dist2 = dist1;
}


어라... 버그가 보이는군요. 무슨 버그일까요.... 잠시 여백을 두어 생각하실 기회를 드리겠습니다... 한 눈 팔지 말고 코드 분석하세요...

한 눈 팔지 말랬잖아요.. 이 이미지를 보시면 이미 한눈 파신 겁니다. (그래도 출처는 http://curiousanimals.net)



자, 문제점을 찾으셨나요? 찾으셨을거라 믿습니다... 아니시라면.... 당신은 프로그래머가 아니야~ 버럭!

그래도 또 설명하는 친절한 포프씨 -_-
위 코드가 하려는 일은 두 거리(dist1, dist2) 중에 dist2가 언제나 dist1보다 크도록 변수값을 교환해주는 거군요. 매우 간단하죠. 근데... 뭔가 이상하죠? temp 변수가 안쓰였다니... 프로그래머가 아니신 분들을 위해 친절하게 예를 들어 한 단계씩 보여드리죠..

1. 일단 대충 변수값을 제맘대로 대입
다음과 같이 변수값을 정해서 이게 왜 버그인제 예를 보여드리겠습니다.

dist1 = 20
dist2 = 10


2. float temp = dist1;
이 라인을 실행하면 변수값이 다음과 같이 됩니다. 별문제는 없죠 아직.

temp = 20
dist1 = 20
dist2 = 10


3. dist1 = dist2; 
이 놈 이후엔 변수값이 이리 됩니다. 역시 괜찮습니다.

temp = 20
dist1 = 10
dist2 = 10


4. dist2 = dist1;  
이게 마지막 라인이군요. 드디어 버그가 보이는군요. 이걸 실행하면 최종 변수값이 이따위가(?) 됩니다.

temp = 20
dist1 = 10
dist2 = 10

 
temp에 저장해눴던 값을 dist2에 대입하는 대신 dist1을 대입함으로 해서... 버그가 생긴거지요...  그럼, 이 버그로 인해서 생기는 문제는 뭐였을까요?

전.모.릅.니.다.

정말 몰라요....(출처: http://knowyourmeme.com)



대충 코드를 훑어봤는데... 파일 이름은 monster.cpp이고 함수이름은 updateTail() 이었습니다. 사실 정확히 어떤 버그가 생기는지는 제대로 살펴보지 않았습니다. 그냥 대충 생각해보니 몬스터들이 팔을 휘두르거나 그럴 때 자취를 보여주기 위해 띄를 하나 그려 주거든요? 가끔, 그 띄가 뒤로 역류해서 겹쳐보이는 경우가 있었습니다. 그게 바로 이 버그 때문일지도 모릅니다. 하지만... 귀찮아서 더 자세히 보진 않았습니다. 그냥

'이 버그 발견했으니 고쳐주세요.'

라고 이메일만 보냈습니다.

버그는 어느 프로그래머나 만든다.
뭐 이정도 버그야 어느 프로그래머도 만들 수 있는 버그입니다. 그 부분에 대해선 프로그래머를 탓하지 않겠습니다. 저같은 꽃미남 프로그래머도 만드는 버그입니다.

뭐, 위의 예는 약간의 비주얼적인 하자.... 별 큰 문제는 아니었죠... 근데... 이게 뭔가 더 중요한 코드였다면 엄청난 하자가 될수도 있죠. 특히나 이처럼 특정조건에서만 생기는 문제였다면 디버깅도 쉽지 않습니다.

하지만 버그를 안만들기 위해 노력은 해야할거 아닌가?
따라서 제가 탓하고 싶은 건 컴파일 경고가 떡하니

"너 뭔가 잘못하고 있을지도 몰라. temp변수가 안쓰였잖아"

라고 말해주는데 그걸 무시한 만행(?)입니다. 

컴파일러 경고를 고치는 것만으로도 상당히 많은 수의 버그를 미리 잡아낼 수 있습니다. 이 코드가 들어가있는 게임... 수백만장 팔립니다... 개발비도 수백만불 됩니다. 이런 프로젝트에서 가장 쉽게 코드품질을 보장할 수 있는 법을 무시하는 프로그래머의 자세 좋지 못하죠. -_-

보통 이따위로 깔끔하지 못하게 프로그래머하시는 분들... 전 타박해 드립니다... 하지만, 이번에는 그러지 못하는 이유가 있었습니다. 그것은....

너도 범인이다.
사실 문제는 이 코드를 작성한 프로그래머에게만 있는 건 아니었습니다. 이 회사의 모든 프로그래머 또는 제대로 된 정책을 만들지 않은 리드급 프로그래머에게도 문제가 있었습니다.

왜냐면..... 이 코드베이스를 컴파일하면 컴파일 경고가 1019개 나오기 때문입니다. -_- 1019개나 되는 경고속에 파묻힌 경고 하나를 찾으라고 하는게 어불성설이지요.....

자네...나보고 어쩌라는 겐가....?


보통 때 같으면 전 이런 경고 다 고쳐버리고,

"앞으로 경고 나오면 경고 하나당 저에게 3대씩 맞습니다."

라고 통보를 해드립니다. 하지만 그럴 수 없었던 이유가 이미 너무 늦었다는거죠.  -_-.... 게임 마무리 단계에서는 아무리 사소한 거라도 안건드립니다. (이건 전에 '게임 출시전 개발자가 갖춰야할 마음가짐'이란 글에서 말씀 드렸었습니다.) 딱히 발견된 버그가 있지 않는한 절대 안고칩니다. 코드를 바꿀 때마다 새로운 버그가 나올 위험이 있거든요. 그래서.... 안고칩니다.... 무조건 안고칩니다.

게임 출시하고 나서 고치죠. 근데 이 프로젝트 이후에 제가 이 팀을 도와줄 일이 없을거 같으니.... 

아마 평생 안고칠지도.... -_-

컴파일 경고를 방지하는 무대뽀 실용적인 방법
자, 그럼 저희처럼 너무 늦기전에 이런 일이 발생하는 것을 방지합시다. 당장 오늘부터라도 시작합시다.

컴파일러 경고를 오류로 처리한다.
가장 실용적인 방법은 컴파일러 경고가 나는 경우 이걸 아에 오류(error)로 처리해서 실행파일 조차 안만들어지게 하는겁니다. 아주 무대뽀 실용적이지요. 간단히 Visual Studio에서 컴파일 옵션만 켜주면 됩니다.
 

아주 실용적(?)인 방법


이러면 경고가 날 때마다 아예 실행파일이 안만들어지니 테스트를 못하지요! 그래서 프로그래머는 반드시 이 경고를 고쳐야만 합니다. 그래야 제대로 도는지 테스트라도 하니.... 근데 문제는.... 임시적으로 뭐 테스트하고 지우기 위해 대충 코드짜놨는데 경고가 나면...... 짜증나지요... 프로그래머들의 반란(?)을 부추기는 계기가 됩니다.... -_-

그래서 이 옵션은 release 빌드용으로만 켜주는게 좋습니다. debug 빌드에서는 프로그래머가 뭔짓을 해도 냅두는게 장수의 비결입니다. 문제는 프로그래머가 debug 빌드에서만 테스트하고 경고있는 코드를 그대로 check-in 했을 때인데요.

뭐, 이럴 때는 자동빌드머쉰(automatic build machine)이 release 빌드에 실패한뒤 그 프로그래머에

"당장 경고를 고치지 않으면 구워먹겠다!"

라는 협박 이메일을 보낼 거라고 믿습니다. 자동빌드머쉰이 없다면 만드세요. 이것도 없이 어떻게 게임 개발하지...? -_-;;;

정말 말도 안되는 경고는 꺼준다
가끔 정말 말도 안되는 경고도 있습니다. 별 의미가 없는 경고도 있고요. 이런 건 꺼주시면 됩니다. 단, 자기 맘대로 끄지 마시고 다른 프로그래머들과 상의한 뒤 동의를 얻어 꺼주세요. 자기 맘대로 끄는 것을 허용하면 경고 고치기 싫어서 그냥 꺼버리는 몰상식한 프로그래머들 꼭 나옵니다. 이런 분들 발견하시면 퇴사처리 해버리셔도 됩니다. -_-

끄는 법에는 2가지가 있습니다. 프로젝트 전체로 꺼주는 법도 있고, 각 파일별로 (또는 그보다 작은 단위로) 꺼주는 법도 있습니다. 원하는 대로 골라서 쓰시면 됩니다.

프로젝트 전체에서 경고 꺼주기
아래처럼 프로젝트 속성에서 꺼주면 됩니다. 아래 예는 프로젝트 전체에서 경고 #4507을 다 꺼주는 겁니다.


파일별로 꺼주기
그냥 아래처럼 #pragma warning()을 써주시면 그 뒤부터는 경고가 안나옵니다.

#pragma warning( disable : 4507 )


이걸 나중에 다시 켜줄려면

#pragma warning( default: 4507 )


을 해주면 됩니다.

대충 정리
뭐... 결국 할 말은.... '경고를 반드시 고쳐주세요.'였으나 역시나 너무나 주저리주저리 써서 대충 정리.
  • 컴파일 경고만 살펴봐도 정말 명백한 버그들을 고칠 수 있다.
  • 릴리즈 빌드에서는 컴파일 경고를 컴파일 오류로 처리해서 프로그래머들이 언제나 경고없는 소스코드를 유지할 수 있게 돕는다.
  • 필요없는 경고는 프로젝트 속성에서 전역적으로 꺼주거나 파일별로 #pragma warning()을 이용해서 꺼준다.

p.s. 앞으로도 대충 어이없는 경험을 바탕으로 '제발 이러지 맙시다.'라는 글을 종종 올리겠습니다. 은근 좋아하는 분들이 많으신듯..... -_-

댓글을 달아 주세요

  1. Favicon of http://gamedevforever.com zinzza 2012.03.16 09:18 신고  댓글주소  수정/삭제  댓글쓰기

    와오~ 좋은 내용 캄사~
    저같은경우는 저런 경고를 보고

    "어? temp안쓰네? 지워야지-_-;"

    하고 한줄을 지워버리는 경우가 종종 있습니다.
    고치는게 아니라 경고를 안보이게 하는거죠... 그리곤 버그를 못찾아요 ㅠㅠ

  2. Favicon of http://blog.naver.com./sorkelf 풍풍풍 2012.03.16 10:35 신고  댓글주소  수정/삭제  댓글쓰기

    역시 포프아저씨~
    저도 컴파일 경고 나오면 왠만하면 다 고치고
    필요없는 부분은 #pragma warning으로 꺼놓는데..
    이 부분을 신경 안쓰시는 분이 의외로 많더라구요 -ㅁ-
    좋은글 잘봤습니다!!

  3. Promotion 2012.03.16 10:43 신고  댓글주소  수정/삭제  댓글쓰기

    잘 읽었습니다. 좋은 내용이네요^^

    공개 라이브러리 같은걸 갖다쓰는경우에는 라이브러리에서 warning이 수천개씩 떠버리는 경우도 있는데,

    그 것 때문에 제가 짠 코드에서의 warning조차도 같이 무감각해질 때가 있었습니다.

    "1000개뜨는거나 1001개 뜨는거나..."같은 느낌으로요

    그럴 땐
    #pragma warning( push )
    #pragma warning(disable : 4705 )
    #include "library.h"
    #pragma warning( pop )

    같은 식의 push, pop을 이용해서 해당 라이브러리가 포함되는 부분만 따로 warning 꺼줄수 있었습니다.

    뭐..애초부터 warning이 수천개씩 뜨는 공개 라이브러리는 쓰면 안되는걸지도 모르지만....ㅠㅠ

    여간, 라이브러리는 어쩔수 없는 상황이라면

    적어도 제 코드만큼은 warning을 제어해주려면 위 방법을 사용하면 됩니다.

  4. Favicon of http://blueasa.tistory.com blueasa 2012.03.16 12:58 신고  댓글주소  수정/삭제  댓글쓰기

    좋은 글 잘 읽고 갑니다. :)

  5. Favicon of http://bluekms21.blog.me 크로스 2012.03.16 13:56 신고  댓글주소  수정/삭제  댓글쓰기

    저한테 C++를 가르쳐주신분이
    '워닝은 원레 다 고치는거다' 하고 알려주셔서.. 그냥 다 고치고 있었지요..ㅎ
    첫번째 temp 퀴즈는 좀 황당했는데 프로그래머가 아닌 분들을 위한 배려였다니..감동~!!

    • Favicon of http://gamedevforever.com 김포프 2012.03.17 08:50 신고  댓글주소  수정/삭제

      아주 훌륭한 선생님을 두셨군요.. 저런 temp 문제는 사실 틀렸다는걸 말해주지 않으면 신경도 안쓰고 으레 맞겠지 넘어가는 사람들이 많죠..

      사람이라면 누구나 ㅎㅎㅎ.. 그걸 비난하진 못함...

      p.s 넵 저 매우 친절합니다.... 그냥 꽃미남에 그치지 않죠.... 친절한 꽃미남 -_-

  6. Favicon of http://Junios.net Junios 2012.03.16 14:42 신고  댓글주소  수정/삭제  댓글쓰기

    저두 경고는 없어질때까지 고치긴 하는데 컴파일러까지 몽땅 다 만들어서 쓰지도 않고 STL도 그냥 써서 어쩔수 없는 경고는 넘깁니다. +_+;;

  7. ipkn 2012.03.16 16:46 신고  댓글주소  수정/삭제  댓글쓰기

    컴파일하면 워닝 4천개 나오는 코드도 봤었어요..... 하루에 천개씩 줄이고 했었는데 orz

  8. Favicon of http://rhea.pe.kr/ Rhea 2012.03.17 02:33 신고  댓글주소  수정/삭제  댓글쓰기

    ..................................찰싹 찰싹 찰싹!!
    버퍼오버플로우 경고 잡아주는 VS만세.

  9. Favicon of http://gamedevforever.com 김포프 2012.03.17 08:49 신고  댓글주소  수정/삭제  댓글쓰기

    전 조만간 static analysis 도 키고 거기 나오는 경고도 다 고쳐볼 생각이라죠. 전에 한번 키니 경고 한 만개 나오던데................. -_-;;;;;;;;;;;;

  10. Favicon of http://gamedevforever.com 친절한티스 2012.03.17 18:35 신고  댓글주소  수정/삭제  댓글쓰기

    전 Warning도 Error 다 라는 생각으로 코딩을 하고 있죠.
    Warning도 다 수정해~~!!!

  11. Favicon of http://gamedevforever.com 죠쉬 2012.03.18 13:10 신고  댓글주소  수정/삭제  댓글쓰기

    워닝 뜨면 엉덩이에 덩 묻은 기분 들지 않나요?
    진짜 어쩔 수 없는 워닝 아니면 후벼 파는 스타일 이라...
    처음에 여럿이 하는 대규모 플젝 들어 갔을때 고치고 싶어서 환장 하는줄 알았...

    폽프님이 글에 쓴대로 사람을 다룬다면 꽤 효율적인 팀이 될거 라는 생각이 드네요
    대신 암살자가 자주 찾아올 듯 ㅋㅋㅋ

    • Favicon of http://gamedevforever.com 김포프 2012.03.19 04:27 신고  댓글주소  수정/삭제

      생명의 위협을 느끼고 있어요.... 이제 보디가드가 필요해요..... 죠쉬님 마눌님 내공이 꽤 되시는거 같던데... 보디가드로 모시고 싶.....

  12. Rocklee 2012.03.21 10:13 신고  댓글주소  수정/삭제  댓글쓰기

    방금 작업중이던 프로젝트의 warnning 을 전부 손봤습니다. 하나 하나 살펴보니 헉.. 하는것들이 몇개 있더라구요;;;; 고치치 않았으면 큰일날뻔했습니다. 감사합니다~ ^^

  13. 지나가던자 2013.02.07 02:08 신고  댓글주소  수정/삭제  댓글쓰기

    뒷북같지만 글 읽고 피식피식 웃었습니다.
    초보시절 선배개발자가 생각나네요. 제 프로젝트 워닝 뜬거 다 고치라고;; 그땐 왜그러시는지 몰랐더랬죠.



티스토리 툴바