Technical Article
_tcscpy, _tcsncpy, _tcsncpy_s 비교 및 올바른 사용법
fiadot_old
2007. 8. 23. 11:58
TCHAR pszMsg[256];
_tcscpy(pktSend.pszMsg, _T("Hello~ Everyone~"));// , sizeof(pktSend.pszMsg));
_tcsncpy(pktSend.pszMsg, _T("5555555555555555"), sizeof(pktSend.pszMsg)); // it's wrong
_tcsncpy(pktSend.pszMsg, _T("5555555555555555"), _countof(pktSend.pszMsg)); // it's right
_tcsncpy의 count인자는 ( Number of characters to be copied.)
복사될 글자수를 의미하는데,
UNICODE나 _UNICODE가 define되어있을때는 wchar가 아닐때는 char가 들어가게 되는데
sizeof를 사용하게 되면 wchar일때 TCHAR pszMsg[256]이
wchar pszMSg[256]이 되어 실질적인 사이즈가 516바이트가 된다.
즉 ,다른부분의 스택 영역에 오버런이 발생하게 되는것이다.
VS2005로 오면서 _countof키워드가 추가되었는데 이 키워드를 이용하게 되면,
Compute the number of elements in a statically-allocated array.
MSDN에 있는 설명대로 배열의 갯수를 반환하게 되는것이다.
single byte나 multi byte나 신경안쓰고 배열의갯수 = 글자의 갯수로 보게 되면
UNICODE선언 유무에 따라 유니코드인지 안시코드인지 결정하게 되는 스트링 관련
함수들(_tcs 접두어가 붙는 CRT String macro functions)은 sizeof대신에 _countof를
사용하면 된다.
좀더 깊이 있게 살펴보자면 Security Enhanced 함수들도 찾아볼수 있는데,
- Checking for NULL values passed to the functions,
- Checking enumerated values for validity,
- Checking that integral values are in valid ranges.
이런 기능들을 해준다.
어렵게 생각할것없이 strcpy_s( ... ) ; 이런식으로, 일반 CRT스트링 함수에 _s 접미사를 붙여주면 된다.
다만 dest영역의 크기를 지정해줘야 하는데, 이부분이 귀찮다면
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
이걸 헤더에 선언해줌으로써 전처리 과정에서 strcpy를 strcpy_s로 바꿔주게 된다.
마지막으로, _tcsncpy와 _tcsncpy_s의 count부분에 sizeof를 사용해서 두 결과의 차이를 비교해보면
_tcsncpy(pktSend.pszMsg, _T("5555555555555555"), sizeof(pktSend.pszMsg));
_tcsncpy_s(pktSend.pszMsg, sizeof(pktSend.pszMsg), _T("5555555555555555"), sizeof(pktSend.pszMsg));
_tcsncpy는 오버런 됐을때 0x00으로 채우게 되지만,
_tcsncpy_s는 0xFD로 채워줌으로 바로 access viloation을 발생시켜준다.