사건의 발단은 VC9으로 테스팅하던 코드를 VC7.1로 포팅하면서 발생했습니다. 이상한 점은 VC7.1이 더 빠른겁니다. ?! 그것도 무려 60%정도였습니다. VC7.1은 STLPort를 사용하고 있었고, VC9은 MS에서 제공하는 녀석을 쓰고 있었지요.
일단, 코드부터 봅시다.
// STLPort 5.2.1 _vector.h:121 typedef _Tp value_type; typedef value_type* pointer; typedef const value_type* const_pointer; typedef value_type* iterator; typedef const value_type* const_iterator;
// MSVC 2008 vector:1886 // 줄바꿈은 제가 한겁니다. @_@ typedef _Vb_const_iterator<size_type, difference_type, _Myt> const_iterator; typedef _Vb_iterator<size_type, difference_type, _Myt> iterator; ..(생략).. typedef iterator pointer; typedef const_iterator const_pointer; typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
두둥. iterator의 타입이 포인터가 아니라.. iterator라는 클래스로 되어 있습니다. 뿐만 아니라, pointer도 iterator클래스로 되어있습니다. 내부를 파고 들어가보니 이렇습니다.
// MSVC 2008: vector:114
// 역시 줄바꿈은 제가..
_Myt& operator++()
{ // preincrement
_SCL_SECURE_VALIDATE(this->_Has_container());
_SCL_SECURE_VALIDATE_RANGE(
_Myptr < ((_Myvec *)(this->_Getmycont()))->_Mylast
);
#if _HAS_ITERATOR_DEBUGGING
if (
this->_Mycont == 0 ||
((_Myvec *)this->_Mycont)->_Mylast <= _Myptr
)
_DEBUG_ERROR("vector iterator not incrementable");
#endif /* _HAS_ITERATOR_DEBUGGING */
++_Myptr;
return (*this);
}
[/cpp]
_SCL_SECURE_VALIDATE라는 Macro를 장렬하게 호출합니다. (.. ) 이 매크로는 _SECURE_SCL 매크로에 의해 제어가 가능한데, 현재 상태가 제대로 된 상태인지 검사해주는 역할을 합니다. 잘못되면 예외를 발생시킵니다. ;;
일반적으로 vector
MSVC 9.0은 단점을 위해 장점을 버린 케이스라고 할 수 있겠습니다. 뭐 성능문제는 _SECURE_SCL매크로를 끄니 5%내외로 낮아지긴 했습니다만.. 왠지 찜찜하군요. 결국 STLPort를 VC9용으로 빌드해버렸습니다. STLPort도 STLP_DEBUG모드로 사용하면, 저런 range check를 해주거든요. 🙂
사실 놀랐습니다. 저런 assertion관련 기능은 Release모드에서 별도로 켜주어야 작동하는게 맞는거 같은데 말이죠. 참고로 _SECURE_SCL을 켜두면 set에서 나는 차이는 더더욱 커집니다. 아무리 CPU가 발달해서 넘쳐나는 세상이라지만, 이건 좀 심하네요. -_-
물론, 개발툴입장에서 개발자의 편의를 추구하는 것은 당연하지만, 이런류의 편의성을 채택할거면 C#이나 Java를 쓰지 누가 C++을 쓰겠습니까. -_-; 디버깅할때나 필요할 법한 기능을 Release모드에 때려박다니.. 무슨 숨은 뜻이라도 있는걸까요. 🙁 뭐 저는 STLPort를 쓰기때문에 딱히 상관은 없습니다만. 🙂
ps1. 표준 관련 호환성은 많이 좋아지긴 한듯 합니다.
ps2. 그냥 STLPort에 투자하면 안되겠니 MS… -_-
ps3. 사고싶어요 징징.
아니 저런, _SECURE_SCL 은 항상 0으로. 저걸 끄고 최적화되면 그냥 단순 포인터와 차이가 없습니다만 (직접 코드 나오는거 보면 포인터++과 같습니다) _DEBUG가 있을 때 1로 하는 건 문제가 없는데 릴리즈일 때도 기본으로 켜는 건 문제가 있긴하죠.
민장이형 이곳까지…
@김민장
단순포인터와 차이가 없기는 한데, 이상하게 약간의 차이는 있더라구요. inlining이 100% 다먹는건 아닌 모양입니다.
그나저나, 릴리즈일때도 기본으로 켜는건 뭔 배짱인지 모르겠습니다.