2010년 1월 15일 금요일

이런 의사 보셨나요? 하우스!


얼마전에 헬스장에서 일이다.

런링머신위에  뛰면서  TV를 보는데   Fox 채널에  하우스 라는 괴짜 의사을 소재로 한
드라마가 하고 있는것이었다  [지금 전편을 구해 보는중이다]

내용을 보면 , 하우스라는 의사가   괴질에 걸린 환자를 , 디버깅?을 통해  환자의 진짜 병이 무엇인지
알아내 치료하는것이었다

마치 프로그래머가  전혀 예측 못하고  , 잡기 힘든  황당한  버그에 맞서 [꼭 멀티쓰레드 디버깅 같은 ]
디버깅 하려는 모습과 같은 모습인것이다

그는 병의 진짜 이유를 위해  병의 증세를 악화시키기도 하지만  병의 원인을  분할 정복시작하는 모습은
분야는 다르지만  대단히 뛰어난 프로그래머를 보고 있는듯한 착각마저 들었다
[ 칠판에 현재 증상으로 생길수 있는 병들을 모두 나열하고 하나씩 체크해 제거하는 방식이 그중 하나다 ]

하우스를 중심으로 의사들끼리 병의 원인에 대해 토론하는 모습도
버그의 원인에 대해 토론하는 프로그래머들과 다를봐 없는것이었다

어떨때는 병의 증상과 원인이 전혀 다르기도 하는데 ,
C언어로 비유 하자면 ,  
메모리를 잘못쓴 코드는 따로 있는데 단지 그 잘못된 메모리를 정상적으로 이용하는 코드에서
뻑이 나버리는 그런 어려운 문제인것이다
 
그런 문제는  디버거로 보더라도  문제의 원인을 제대로 알기 힘들다

대체로 포인터를 잘못 사용한게 원인인데 , 코드를 짠 사람이 포인터를 어떻게 사용하는지에 대해 체크해
원인을 찾는게 차라리 빠르다
[ 일단 무조건 멀티쓰레드로 돌아가는게 있으면 그것부터 끄는게 도움이 되기도 한다 ]
[혹 메모리 값이 변할때 break가 걸리게 하는 방법도 대안이 되려나?]

그것과 비슷하게   미스테리한 괴질에 대해
하우스는 환자의 몸상태나 증세를 보기보단 , 그의 환경 및 습관
어떤것을 숨기고 있는가를 살펴보기 시작한다

또한 환자나 보호자의 거짓말 혹은 실수의 여부도 집중 추궁하기도 한다.
그리고 거기서 단서를 얻는다
[ 거기서 환자나 보호자의  거짓말들은    프로그래머가 버그에 대한 어설픈 변명? 혹은 거짓말을
지어내는것과 같아 보였다 , 나 역시 버그에 당황하면 어설픈 변명을 늘어놓았던 기억이 난다 ]

심지어 불법으로 환자의 집에  부하?의사들을 침입시켜 , 환자의 현재의 증상이 아닌 , 환자의 환경을
체크하기도 한다

프로그래밍으로 따진다면
애초부터  그런 증세가 유발될수밖에 없는  잘못된 환경(설계)로 인한것인가를 따져보는것을 더 중히 여기는것이다

그리고 드라마 내내 자주 반전이 있는데 , 원인을 알아 치료약을 투여해 치료가 된것처럼 보이지만 결국
다른 증상이 생겨버리던가 , 같은 증상이 재발해버리는것이다

프로그래밍에서보자면 ...
우리가 버그의 원인이 되는 코드를 찾았고  그 코드를 수정해 버그를 고쳤다고 생각했지만
결국  버그가 재발하는 모습과 똑같았다 [진짜 버그가 아닌것이다]


뭔가 통하는게 있지 않은가?  


재밌는것은 죽은 사람도 살려 냈다는 소문난 명의 이야기에서도 비슷한것을 찾을수 있다

위나라의 임금이 편작에게 묻는다.
"그대 삼형제 가운데 누가 제일 잘 병을 치료하는가?

" 큰 형님의 의술이 가장 훌륭하고 다음은 둘째 형님이며 저의 의술이 가장 비천합니다.

임금이 그 이유를 묻자 편작이 대답한 내용은 이러했다.


"큰 형님은 상대방이 아픔을 느끼지 전에 얼굴빛을 보고 그에게 장차 병이 있을 것임을 알아서 그가 병이 생기기도 전에 원인을 제거하여 줍니다. 그러므로 상대는 아파보지도 않은 상태에서 치료를 받게 되고 따라서 그간 자기의 고통을 제거해 주었다는 사실을 알지 못합니다. 큰 형이 명의로 소문나지 않은 이유는 여기에 있습니다.

둘째는 상대방이 병세가 미미한 상태에서 그의 병을 알고 치료를 해줍니다. 그러므로 이 경우의 환자도 둘째형이 자신의 큰 병을 낫게 해주었다고 생각하지 않습니다.

그러나 나는 병이 커지고 환자가 고통속에 신음할 때가 되어서야 비로소 병을 알아 보았습니다. 환자의 병이 심하므로 그의 맥을 짚어야 했으며 진기한 약을 먹이고 살을 도려내는 수술도 했습니다. 그런데 사람들은 나의 그러한 행위를 보고서야 비로소 내가 자신의 병을 고쳐주었다고 믿게 되었죠. 내가 명의로 소문이 나게 된 이유는 여기에 있습니다."


여기서 큰형님의 치료를 보면 애초부터 버그를 유발하지 않겠끔 설계를 한다고 볼수 있겠다

코드 컴플리트(Code Complete)의 저자 스티브 맥코넬도 초보 프로그래머 시절에는  머리에 생각나는데로 짜다가
버그때문에 고생하였고, 중급 프로그래머로 올라오고 나서야  디버깅에 고수가 되었다고 한다
하지만 , 디버깅을 잘하는건 프로젝트을 성공하는데 큰 도움이 되지 않았다고 한다
디버깅을 아무리 잘해도 , 버그가 계속 나오는 구조라면 무슨 의미가 있겠는가?
아예 디버깅을 할 필요가 없는  즉  아예 버그를 유발할 가능성이 적은 설계를 하는게 최고였다는것이다.  

그래서 인지 설계에 통달하지 않으면 쓸수 없는  Code Complete라는 책을  내지 않았겠는가?

여담이지만 ,예전 해커 한분을 본적이 있는데 그는 코드를 짜면  코드를 짜는 그 순간 모든것이 컴파일 타임때
모든 논리가 완벽하게 정리되어야 한다고 생각하신분이었다 , 한마디로 디버거가 필요 없다는 것...
수학처럼 완벽함을 추구하는 분이었다 .   컴파일타임에 모든 물리적(?), 논리적 에러까지 이미 처리가능한 (믿기는 힘들었지만)

구루들은  대체로(?) 디버깅 자체가 필요없는 설계자인것이다

여기서 우리는 의학에서의  진단과  프로그래밍의 디버깅에서 통하는점을 찾을수 있었다
마치 건축과 프로그래밍의 설계와의 공통점을 찾는것과 비슷한 느낌인것이다 [디자인 패턴]

왠지 의학을 공부하고 싶은 생각마저 드는 이 드라마를 통해 무엇인가  배울수 있는 무언가를
찾을수 있을것만 같은 느낌이다 , 물론 재미와 감동 역시 빠질순 없다

아직 이 드라마를 보지 못햇다면 , 꼭 볼것을 추천한다
당신이 프로그래머라면   무엇인가 통하는 느낌을
받으리라......

여담으로

난 아직 버그를 유발하지 않을 최선의 설계는 알지 못하지만 assert로  인자 와 리턴 값 그리고
포인터 접근에 관한것 꼼꼼히 걸어둔다 , 최선의 설계를 알지못하면 이러한 방어적 프로그래밍이라도
잘해두는게 차선은 아닐까라는 생각도 해본다  


2010년 1월 13일 수요일

STL로 범한 죄악

신입때 opengl로 2D 엔진을 개발할때였다.

한글을 찍기 위해 조합형 한글 방식을 취했는데
한글자당 자음 모음 자음 형태로  찍어야 했으므로 글자당 필요한  인덱스가 3개가 필요 했었다

그리곤 , 아무 생각없이 인덱스를 받아  해당 택스쳐 위치를 찍어 한글을 만들어 냈는데...
글짜를 찍는 순간부터 cpu가 무려10%이상 오르는  황당한 경험하게되었다
( 디버깅 모드였던걸로 기억한다, 그래도 터무니 없긴 마찬가지;;)

아무리 봐도 글자가 이렇게 큰 부하가 걸릴거라고는 생각못했는데 , 너무 많이 부하가 걸리는것이었다
의심되는 코드를 찾아보아도 딱히 그럴만한 작업을 한게 없었다

아무리 눈으로 코드를 보더라도 , 눈으로는 확인할수 없어
나름 허접한 프로파일링 끝에 아래와 같은 코드가 모든 악의 근원인것을 알게되었다


// 겉보기에는 문제 없는 코드
void GetXXIndex( std::vector<int>* pIndexVec)
{
     pIndexVec->push_back(1)
     pIndexVec->push_back(2)
     pIndexVec->push_back(3)
}

겉 보기에는 아무런 문제가 없고 멀쩡한 함수처럼 보인다

하지만 저 함수가 일으킨 문제는 로직부하의 30%가 넘을만큼  터무니 없는 수치인것이다

도데체 왜 문제가 된것일까?

일단 가장 핵심적인 사항으로는 글자를 찍는 만큼 저 함수가 호출되므로 , 매 프레임당
수십에서 수백번까지 호출되어야 했다는 것이다
결국  글자가 많아질수록 저 함수 호출은 늘어나는 구조고 , 그 무지막지한 부하가 비례 했다는것이
결정적인 문제였다

하지만 단순히 함수호출이 많다고해서 부하가 크게 걸리린다는건 어불성설이고

일단  가장 상식적인 것으로는 컨테이너에 담길 갯수가 3개라는 것을 알면서도
가변 크기를 담는 vector를 선택한게 문제가 아닐까라는 결론에 이르게 된다 ,

물론 STL에서 권장하는 vector의 reseve 함수를 생략하긴 했다 [이놈의 귀차니즘...]
인지하고 있던 사항이지만  , 그래도 터무니 없지 않나 라는 생각이 들었던것이다

아니 이런 생각부터 잘못됐다 , 3개라는 걸 알고 있었으면 고정 크기 배열을 넘겼어야 하는것이
원칙인것이다

그렇다 정답을 알면서도 대충 vector를 남용한 결과를 다시 확인하기 위해
vector 의 소스를 보며  메모리 할당 정책을 다시 훌터봐야 했다

물론 STL책에서 이미 알고 있던 사항들을 재 확인하는것에 불과 했지만
[
   _Capacity + _Capacity / 2; // try to grow by 50%  
   그래도 작으면 늘어난 size만큼 capcity를 늘림
 ]
즉 현재 크기가 메모리 할당량보다 크면 , 메모리 할당양이  50% 크기가 증가하는 코드였던것이다
[이건 STL 구현마다 다르다]

따라서 3번의 push_back 모두  메모리 재할당이 일어나는 코드가 된것이다
재할당은 new delete를 필연적으로 불러오고 결국 저 함수는 new1[1] delete ,  new[2]  delete ,
new[3] delete 를 반복한 코드와 같다
[ 참고로 어느정도 크기가 되야 , 저런 무식한 할당에서 피할수 있게 된다 ,
예를 들어 100 이면 다음 크기는 150이 되므로 50번의 push_back으로부터  추가적인 메모리 할당을
피할수 있게 된다]

그런데 수십에서 수백번까지 지속적으로 반복해서 저 함수를 불리었으니  
매 프레임당 수백번까지 메모리 재할당를 하게 된것이다
[ 플레폼마다 힙메모리 관리가 다르기도 하고 , 성능 차이가 존재하기도 하기에
  힙관리의 부하의 차이는 당시 플레폼에 의존한다  ]

이 처참한 결과를 확인하고 단순히 vector를 고정 배열로 넘기자  그 무지막지한 cpu 사용량은 거의 사라져 버렸다
 그리고 그 함수의 호출 갯수에 비례해 늘어나던 cpu 소모량은 거의 발생하지 않았다
한마디로 고정배열을 넘기게 함수를 바꾸자    부하가 아예 없는 수준으로 바뀌었다

이 같은 경험으로 힙메모리의 무분별한 사용은  상상 이상의 부하를 초래한다는것을 깨달았고
말로만 듣던 new delete의 폐해를 당시 처음으로 느꼈었다
[그렇다고 , 어느 자료구조든 같은 문제를 앉고 있기때문에 STL만의 문제는 아닐것이다
문제는 역시 쓰는 사람일것이다]


오랜 고민 끝에 이 같은 문제에서도 ,  vector와 같은 인터페이스로 문제를 해결하고 싶은 욕심이났다
그래서 만든것이 fix_vector이다

[fix_vector 자료실 링크가 깨진관계로 다시 여기에 올립니다]

 개인적으로 라이브러리를 완벽하게 만드는건 어렵기때문에  기왕이면 검증된  라이브러리를
가져다 쓰려노력한다 , 하지만  fix_vector 같은건 절대 만나볼수가 없어 , 결국 직접 만들어버렸다

나름 배열이 사용되어야 할곳에 적절히 쓰이면 쓸만한거 같았다



2010년 1월 8일 금요일

STL은 정말 괜찮은 물건인가?


자료구조와 STL를 제대로 공부를 해봤다면 정말  이런 질문 자체가 어이 없게 느껴질지 모르겠다

하지만 현실은 그렇지 않다  , 아직도 종종 꽤 많은 프로그래머입에서  
"STL 따위는  쓰지 말아야 한다"고 주장하는 글이 보이기 때문이다

다시 말하자면 한마디로   "STL 코드를 보면 지저분하고 별거 없는거 같다" 라는것이 그들의 주장인것이다
그리고는 자신이 짠 코드가 STL를 압도적으로 능가한다고 주장하는 경우가 일반적이다

과연 그럴까?

내가 겪어본 봐로는
그들의 주장은 STL의 익숙하지 않거나 자기의 코드에 대한 막연한  우월감 때문인 경우가 대부분이다

좀더 정확하게 말해
아마 STL 코드를  살짝보니 , 템플릿 도배에 지저분해보이고,  
"저정도는 내가 더 깔끔하게 짤 수 있어"  같은  치기어린 감정을 나타내는 주장 밖에 없다

워낙 많은 C++ 커뮤니티에 그런 사건이 있어왔기에 ,  어쩌면 이제는 식상한 이야기 일수 있으나
그래도 그나마 가장 나름의 논리를 가지고 있던 한분이 있어  링크를 걸어본다

gpg study에서  그나마 stl를 대안할 라이브러리를 준비했다고 주장해  장장 15페이지나 되는 토론을
벌였는데 ,  이글에서 각자  결론를 내려볼수 있겠지만  특정한 용도의 라이브러리를
 범용적인 STL에 적용하려니 문제가 되는게 일반적이었다


이부분을 보면 내가 C++의 최적화의 필독서라 불리는 Efficient C++의 내용을 인용하였는데
좀더 이분야의 전문가 글을 인용하는게 도움이 될거 같아  글을 올렸다
혹시라도 C++ 최적화에 관심이 있다면 반드시 읽어봐야 할 책이다
[나 역시 2번은 읽었다]


참고로 위 링크에서 내가 저렇게 길게  토론을 한 이유가 있는데
STL를 깔보는 프로그래머에게  , 쓸때 없는 소리를 더 이상 하고 싶지 않았기때문이다

헛소리를 하면 그냥 저 링크를 걸고 ,  저기 나온 내용을 이해를 하고도  STL를 깔수 있느냐라고
하면  아마 "게임 끝" 이 날테니 말이다

그래도 왠지  STL 험담을 하고 싶다면  제발 자료구조 책과 STL에 대한 책 한권쯤은 읽어봐라

자료구조책에 나와 있는 모든 내용을 C++ 템플릿으로 이렇게 완벽히 소화해낸 라이브러리가
있을까 하며 기쁨의 눈물을 흘릴것이다

또한 구루들이 컴파일 타임때 최대한 최적화한 STL를 만들때 얼마나 많은
고민을 했을까 라는 생각이 들때쯤이면 한층더 프로그래머로써 성숙해질 수 있는 게기가 되리라...

여담이지만
Effective C++  시리즈의 저자 스캇마이어는  More Effective C++ 에서 스마트 포인터에 대해
상당한 페이지를 소모하며 글을 작성하였고 그 라이브러리를 공개도 하였다

정말 멋지게 만들었음에도 , 그가 정말  C++ 바닥에서는 알아주는 구루임에도 불구하고

More Effective C++ 책 다음작품인  Effective STL책 에서  자기가 만든 스마트 포인터를 쓰지말고
boost의 스마트 포인터를 쓰라고 간곡히 권한다

자기도 심열을 기울여 만들었지만 ,  모든 상황을 체크할수 없었고 , 꾸준한 버그 리포팅을 받다가
결국 포기하였다는것이다

그만큼 표준 라이브러리나 검증된 라이브러리를 만들기 어렵다는 것인데 ,
STL 험담하기전에 자신의 실력를 한번 되돌아 보면 좋을거 같다

------------------------------------------------------------------------------
혹 Effective C++ 시리즈 책을 모르는다면  반드시 읽어보아라  
[  나 역시 평균 3번은 읽어보았다 ]
------------------------------------------------------------------------------

다음 편은 fix_vector를 다뤄보겠다

2010년 1월 6일 수요일

C++ 에서 힙메모리를 자동으로 관리하게 코드를 작성하자


아직도  C++은 동적메모리를  new delete로 관리 하여만 한다고 생각하는 사람이 많은것 같다

지금도 남이 짜 놓은 수 많은 코드속에서 new로 생성한 객체를  더미(raw)  포인터에 그냥 담고 ,  
"언제가 delete가 필요할때  완벽하게 delete 해줄수 있을거야" 라는 식의 코드를  보고 있는중이다
(오해는 없길 바란다 누굴 비난하기 위한 내용은 아니다)

이런 설계는 언제나 그렇듯 처음에는 무난한 ??? 설계가 될수 있으나
코드는 항상 수정되어야 하는 경우가 대부분이기때문에 수정할때마다
이 수많은 경우의 수를 다 파악해 delete 코드를 넣어주는 지옥과 같은 경험을 하게 된다

그래서 이러한 코드를 보게되면 ,코드 분석보단   " 아마 메모리 관리가 이렇게 힘들어서야... "
같은  반복된 생각만 든다

"이 중구 난방식의 new속에 , 도대체 delete를 어떻게 완벽히 기억해내어  처리해주지?"

 실용주의 프로그래머 책의 저자가  그러지 않았던가 ,  
'문제는  어떻게  완벽히 기억할수 있는게 아니라, 언제 잊어버릴것인가' 이다 [물론 정확한 인용은 아니다]

알고리즘의 핵심이 아닌상  , 잘잘하고 구차한 문법문제는  
잊어버려도 문제가 없는 코드가 구성되어야 좋은 코드라 할수 있는것이다.

자바가 C++ 프로그래머를 대량으로 흡수할때 1순위로 강조한것이 무엇인가?
가비지 컬랙션이 아니었던가?
쓸때없는 것에 머리 쓰지 않아도 되는건 대단한 강점인것이다

소실적에는 c++에 가비지 콜랙션을 만들수 있지 않을까하는  생각도 해보았으나
이런 당연하고도 고전적인 문제를 C++이 해결을 못했을리는 없다

믿을지 모르겠지만  나는 약 6년전 대학교때 STL과 BOOST를 공부한 이후 단한번도 직접 delete를 작성한적이
없다. 혹!? 모르나 아마 없을것이다
[물론 crt 디버그에서 메모리릭이라 투털거린적 역시 없다]

믿을수 없다고 ??

지금 말한 3가지만 사용한다면  앞으로 99.9%  delete를 직접 할 필요가 없다
1. 스트링
2. 자료구조
3. 스마트 포인터


1.  스트링
c언어 스트링은 가장 고전적이고 다루기 어려운 구조이다
스트링 특성상 가변적으로 크기가 변하는게 대부분이기때문에
동적 메모리를 활용하는 경우가 많고 , 경우에 따라서 관리가 복잡하다

하지만 스트링 객체를 쓰면 대부분 해소 되는데
표준 std::string이 아니더라도  스트링 객체를 활용한다면 구질 구질한 c언어 스트링으로 인한
new char[XX]같은  동적 메모리 사용을 피할수 있다

아직도 문자를 생성할때  new char[XX] 쓰고 있다면 반드시 표준std::string 를 이용해보자
다른 세상을 경험할수 있을것이다

그런데도 굳이 스트링 객체 자체를 new로 생성하는 몰지각스러운 코드를 만나면 답이 안나온다
스트링 객체를 대부분  그렇게 생성되어야 할 이유가 99%이상  없기때문이다

2. 자료구조
C++의 대표적인 자료구조로는 STL이 존재한다
STL이 객체를 다루는 방법이   복사를 이용하기때문에 주로 가벼운 객체를 주로 담게되나
어지간히 무겁지 않는한  복사가  new 로 할당해 담는 비용보다  훨씬 싼편에 속한다
만약 정말로 무겁거나 객체의 다형성을 위해 new를 이용해야 한다면 스마트포인터를 담으면 그만이다
 스캇마이어(Effective STL)가 그리 강조하지 않던가?

컴퓨터 공학생이라면 필수로 읽어봤을 자료구조책에   당골로 등장하는
vector list hash map deque 등 [이름은 조금 다를수도 있다] 을
STL를 이용하면 공짜로 이용할수 있으며
이것은 곧  가면적으로 크기가 변하는 컨테이너를 공짜로 사용할수 있다는 말이다

new를 이용하는 가장 핵심적인 이유중 한가지가 가변 크기때문 아니던가? 그것을 자동으로 STL
컨테이너가 해주기때문에 new를 쓸이 없어진다
[물론 hash나 set, map은 그뿐이 아니라 , 키로 데이터 관리까지 해주니까 두말할 나위가 없다]

그중 new를 이용한 배열의 경우

 vector를 이용하면 C의 배열과 100% 호환되기때문에 그대로 C API와 더불어 운영될수 있으며
컴파일러의 최적화 능력 [STL의 성능은 다음에 다루기로 하겠다]
까지 더해지면 vector의 편리함과 C배열과 같은 성능을  동시에 누릴수도 있는것이다
게다가 수백만명이 검증한 STL 자료구조의 안정성도 더불어 누릴것이다

3. 스마트 포인터
new 직접 사용에 대해 계속해서 부정적인 이야기를 했지만
반드시 직접 힙메모리를 이용해야 하는 경우가 존재한다
다형성이 존재하는 객체를 컨테이너에 담을때 부모형태로 포인터를 저장해 관리 할때는
대부분 new를 피하기 어렵다
그래서 생겨난것이 스마트 포인터이다
[ 물론 객체 크기가 커서 new로 생성해 스마트 포인터에 담는 경우는 예외이다 ]

스마트 포인터의 기본 이념은  new생성된 포인터를  객체가
참조 카운팅(std::auto_ptr 같은것은 제외) 관리해서 유지하는것이다

참조하는 객체가 전부 사라지면 그때에 delete 된다

가장 대표적인게 표준으로도 포함된 boost::shared_ptr이 될것이다 [boost.org의 doc를 참조하라]

기본적으로 가비지 컬랙션을 사용하는 언어들도 내부적으로는 참조 카운팅을 유지하고 있다
[원리는 같다는 것! ,다만 C++은 참조하는 객체가 사라질때 바로 제거 된고 , 다른 언어들은
언어의 가비지 컬랙션 정책에 따라 다를것이다 ]


물론 만능은 아니다
스마트 포인터를 이용할때   내부의 스마트포인가 서로를 포함하는 구조로 객체가 구성될 경우
참조 카운팅이 꼬여 메모리가 해제가 안될수 있는것이다

그것을 위해 weaken 어쩌구 방식의 스마트 포인터도 boost에서 지원하는데
그러한 꼬임은
그것은 C++의 스마트 포인터가 아니라 가비질 컬랙션을 지원하는
어떤 언어에서도  정상적인 방법으로 메모리를 해제할수가 없다

다른 언어에서도 boost의  weaken 어쩌고 같은
방식을 이용해야 한다 , 한마디로  상호 포함관계의 스마트 포인터는  정상인 논리 구조라 보기 힘들다고 생각한다

그것을 이용할 정도면  설계 자체가 이해하기 어려운 구조기때문에
설계를 바꾸는게 정답일것이다

---------------------------------------------------------------------------------------------------
참고로

boost의 shared_ptr은  delete 뿐 아니라 직접 제거자를 지정해 주어
delete 대신  다른 해제 방법을 이용할수 있게 해놓았다
new로 생성하지 않고 create나 destroy를 이용해야 하는 리소스도
대응해서 사용할수 있는것이다

혹 STL에 스마트 포인터를 담으면  참조할때  이터레이터 참조뿐 아니라 스마트 포인터를 참조해야하기에 **iterator를 쓰게되어 가독성이 떨어지 거슬리는분들이 존재할거라 생각된다
나 역시 그랬으니까

그건 boost의     boost/ptr_container/ptr_list.hpp 같은걸 이용하면 된다
부스트의 ptr_containter에는  new로 생성된 포인터를 직접 넣어주면
컨테이너에서 제거 될때 자동으로 delete를 해준다
 
----------------------------------------------------------------------------------------------------


STL 스마트 포인터 알게된지 이후 6년동안 delete 코드를 작성해본적이 없지만
힙메모리를 이용하고도  , delete 코드가 없다하면 아직도 믿지 못하는 사람이 많다

gpg study에서도 비슷한 발언을 했을적에  믿기 힘들다는 사람을 대다수인걸보면
얼마나 많은 사람들이  아직도  힙메모리를 직접 다루고 있는지 느껴지는듯했다


프로그래머라면 정말 중요한 알고리즘을 기억하는데만해도 머리에 담을 용량이 부족하지
않았던가?


다음 편엔 STL 자료구조에 대해 이야기 해보겠다
덤으로 fix_vector도 ~ ^^