'strncpy'에 해당되는 글 2건

  1. 2015.02.07 strncpy 와 strncpy_s 에 대한 오해
  2. 2015.02.07 strncpy 의 함정
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

strncpy()는 복사되었으면 하는 문자열의 길이를 넘어서지 않게 복사해 준다. 
그리고 대상 버퍼를 넘어서게 되면 NULL로 끝나지 않는 문자열까지 복사하게 된다. 예를 들면 아래와 같다. 

strncpy(dest, 8, "1234567"); // dest == { '1', '2', '3', '4', '5', '6', '7', NULL } 
strncpy(dest, 8, "12345678"); // dest == { '1', '2', '3', '4', '5', '6', '7', '8' } 


strncpy_s() 는 대상 버퍼가 실제 수용가능한 크기와 복사되었으면 하는 문자열의 길이 두가지를 넘긴다. 
strncpy()와 strncpy_s()의 다른점이 있다면 strncpy_s()는 '복사 되었으면 하는 문자열의 길이'를 넘어서서 복사를 할 때 마지막을 항상 NULL로 끝나게 해준다는 점이다. 

다음과 같은 코드는 런타임 에러를 발생시킨다. 

// 이 코드는 buf에 1, 2, 3, 4, 5, 6, 7, 8, NULL .. 총 9개의 문자열을 넣으려다가 에러가 나게 된다. 
char dest[8]; 
strncpy_s(buf, _countof(buf), "123456789000", _countof(buf)); 


따라서 strncpy_s()를 사용할 때는 버퍼 크기와, 복사하고 싶은 길이를 다르게 주어야 한다. 

char dest[8]; 
strncpy_s(buf, _countof(buf), "123456789000", _countof(buf)-1); 


참고. 

strcpy_s()를 사용하면 버퍼 크기를 넘어서는 데이터를 넘을 때 
자동으로 막아준다고 착각하는 경우가 있다. (strncpy처럼) 

strcpy_s()에 넘기는 2번째 인자인 dest_size는 '내가 이 정도까지만 복사하고싶다'의 의미가 아니라 
'여기 지정한 크기를 넘어서 복사하려고 하면 프로그램을 멈추고 에러창을 띄워라' 의 의미로 보아야 한다. 

// 이 코드는 이쁘게 dest에 1234567까지만 복사해 주는 것이 아닌, 프로그램을 뻗게 하는 코드다. 
char dest[8]; 
strcpy_s(dest, _countof(dest), "123456789"); 


연장해서 sprintf_s() 와 _snprintf_s() 에도 똑같이 적용된다. 

sprintf_s(buf, _countof(buf), "%s 1234567", "1212"); // 프로그램 오류를 내는 코드 
_snprintf_s(buf, _countof(buf), _countof(buf), "123456789%d", 121212); // strncpy_s()와 같은 이유로 오류를 내는 코드 
_snprintf_s(buf, _countof(buf), _countof(buf)-1, "1234567%d", 121212); // 정상적으로 작동하며, 이렇게 써야 하는 코드


출처 : http://gpgstudy.com/forum/viewtopic.php?p=97501

'Programming > C / C++' 카테고리의 다른 글

레지스트리의 값 가져오기  (0) 2015.02.07
# 과 ##  (0) 2015.02.07
함수 포인터 typedef  (0) 2015.02.07
enum, 보다 나은 enum  (0) 2015.02.07
vector 와 map 의 erase 를 할때 주의점  (0) 2015.02.07
Posted by 역시인생한방
,
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

코딩을 하다보면 발생하는 버그중 가장 악질적인 것중 하나가 디버그 버전에서는 나타나지 않고 릴리즈 버전에서만 나타나는 버그다. 그것도 랜덤하게....

랜덤하게 나타나는 버그 중에서도 자신이 만든 루틴에서 나는 버그는 그나마도 괜찮다고 할 수 있다. 악질 중에 악질은 아무 생각 없이 쓴 표준 함수에서 나타나는 경우다. 특히 표준 함수를 쓸 때는 대부분이 아무런 문제가 없다는 확신을 가지고 쓰기 때문에 더욱 찾기가 힘들다.

DJ Max때도 그런 악질 적인 버그를 한번 만난 적이 있다. 릴리즈모드에서만 가끔씩 랜덤으로 유저가 튕겨져 나간다는 것이었다. 디버그 모드에서는 아무리 해도 찾을 수 없는 그 버그의 원흉은 아무런 생각 없이 썼던 strncpy() 함수에 있었다. 물론 코드를 검사할 때 strncpy()함수에 큰 주의를 기울이지 않기 마련이기 때문에 더 찾기가 힘들었다.

아마도 코드는 이랬던 것 같다.


char szDst[256];

// szStc 는 인수로 넘어온 const char* 형 변수다.
strncpy(szDst, szSrc, 2);

// 이하 이어지는 코드...


아마도 고수분이라면 이 코드의 문제점을 바로 알아봤을 것이다. 따로 놓으면 보이지만 이 코드가 수만줄 사이에 끼여져 있다면 참으로 찾기 힘든 코드다.

이 코드 발생 원인에는
첫번 째로 초기화에 충실하지 않았다는 점이고 두번 째로 strncpy()의 정의를 확실히 몰랐다는 점을 들 수 있겠다.

보통은 문자열을 주어진 길이만큼 복사한다고만 알고 있는 strncpy()의 확실한 정의는 이렇다.

"문자열을 정해진 길이만큼 복사한다. 소스 문자열의 길이와는 별개로 무조건 정해진 길이만큼 복사되기 때문에 문자열이 짤릴 수도 있고 뒷부분이 NULL문자로 채워질 수도 있다. 채워넣을 문자열 크기는 주어진 길이보다 커야 한다. 그렇지 않으면 인접 데이터가 파괴된다."

여기서 주의해야 할 것은 주어진 길이만큼 복사한다는 내용 이외의 것이다. 다시 위의 코드로 돌아가보면

szSrc로부터 szDst로 2개의 문자가 복사된다. 이 경우 문자열중 앞쪽 2개만 사용할 때는 문제가 없지만 2개를 넘어갈 때는 세번째 멤버부터는 데이터를 보장할 수 없기 때문에 문제가 된다.

이 코드를 고칠려면


char szDst[256] = { 0 };
을 해주던가

strncpy(szDst, szSrc, 2);
이후에

szDst[2] = 0;


을 붙여주어 채워지지 않은 나머지 부분에 널문자임을 확실히 해 주어야 한다.


출처 : http://trapping.egloos.com/2509570

'Programming > C / C++' 카테고리의 다른 글

자료형의 종류와 범위  (0) 2015.02.07
__IN & __OUT  (0) 2015.02.07
XOR Swap  (0) 2015.02.07
struct tm  (0) 2015.02.07
Lotto  (0) 2015.02.07
Posted by 역시인생한방
,