VC에서 _MSC_VER를 이용해 컴파일러에 따른 특성을 적용하는 방법

_MSC_VER를 이용한

VC에서는 _MSC_VER라는걸로 컴파일러 버전이 정의되어있으므로, 이를 이용할 수 있다.

#if _MSC_VER >= 1500
    // VC9, VC 2008
#elif _MSC_VER >= 1400
    // VC8, VC 2005
#elif _MSC_VER >= 1310
    // VC7.1, VC 2003
#elif _MSC_VER > 1300
    // VC7, VC 2002
#elif _MSC_VER > 1200
    // VC6, VC 6.0
#elif _MSC_VER > 1000
    // VC5, VC 5.0
#endif

이 버전은 cl.exe /?를 했을 때 표시되는 버전의 앞부분을 보면 된다. 예를 들어, VS2008SP1의 경우 "15.00.30729.01(80x86)"와 같이 표시되는데 앞의 숫자 4개인 1500이 _MSC_VER가 된다.

(더 자세한 설명이나 예제는 구글링으로 쉽게 얻을 수 있으므로 생략한다.)

똑같은것만 쓰면 의미가 없으므로(?), 나는 좀 다른짓을 해보겠다.

안전한 함수와 warning C4996

VS2005부터는 안전한 함수라는것이 추가되면서, 이전 코드를 빌드했을 때 warning C4996를 내도록 변경되었다. 주1

경고가 나는게 영~ 거슬리는데, 그렇다고 안전한 함수로 다 바꿔버리면 예전 컴파일러에서는 안돌아가게되는 문제가 생긴다. 그래서 꼼수로 다음과같은 코드를 고려할 수 있다.

#if _MSC_VER < 1300
    #define strcat_s(DES, MAXDESLEN, SRC)   strcat((DES), (SRC))
#endif

이렇게 하면 쓸때는 항상 안전한 함수 형식을 쓰고, 컴파일러에서 안전한 함수를 지원하지 않을 경우에는 기존 함수를 사용하도록 할 수 있다.

이 방법의 단점은, 컴파일러에 따라 프로그램의 동작이 달라진다는 점이다. 만약 des의 공간이 충분하지 않으면, 안전한 함수를 지원하는 컴파일러에서는 나머지를 무시하지만, 안전한 함수를 지원하지 않는 컴파일러에서는 buffer overflow 문제를 일으키게된다.

c++이라면 inline을 이용해서 다음처럼 만들 수도 있다.

#if _MSC_VER < 1300
    inline errno_t strcat_s(char *des, size_t maxdeslen, const char *src) {
        if ((des == NULL) || (src == NULL)) {
            return EINVAL;
        }
        if ((maxdeslen <= 0) || (strlen(src) > (maxdeslen - strlen(des)))) {
            return ERANGE;
        }
        (void) strcat(des, src);
        return 0;
    );
#endif

아마 실제 strcat_s()의 구현도 이와 비슷하지 않을까 싶다.

참고로 위 inline 코드는 알고리즘만 표현한거지 검증해본건 아니므로, 버그가 있거나 컴파일 자체가 안될 수도 있으므로 주의. -_-;; (디버깅은 알아서 하시라;)

  1. 안전한 함수가 언제부터 추가되었는지는 확실히 모르겠는데, MSDN 등을 보면 대충 2005 때부터 추가된 것 같다.
이올린에 북마크하기(0) 이올린에 추천하기(0)

, , , , ,

2009/04/02 14:00 2009/04/02 14:00
Trackback Address:http://reznoa.wo.tc/blog/trackback/321
[로그인][오픈아이디란?]