2016-06-10 10 views
1

this에 따르면 StackOverflow 주석 strncpy은 비 고정 길이 배열과 함께 사용하지 않아야합니다.Strncpy는 고정 길이 배열에만 사용해야합니다.

strncpy은 구조체/이진 파일의 고정 너비가 아닌 필수 문자열 필드로 작업하지 않는 한 절대로 사용하지 마십시오. - 16시 22분

에서 R .. 1월 11일 '12 나는 당신이 동적으로 문자열에 대한 메모리를 할당하는 경우 중복이지만 strcpy

이상 strncpy를 사용하는 것이 나쁜 것이 이유가 있다는 것을 이해
+1

여기에서 답을 찾을 수 있습니다 (http://stackoverflow.com/questions/1258550/why-should-you-use-strncpy-instead-of-strcpy) –

+0

이유는 그것은 당신이 생각하는 것을하지 않는다는 것입니다. – immibis

+0

어떤 목적으로도 strncpy를 사용하면 안됩니다. 본질적으로 안전하지는 않습니다 ([this this] (http://stackoverflow.com/questions/2114896/why-are-strlcpy-and-strlcat-considered-insecure)). 대신에,'strcpy'를 버퍼 크기 검사와 함께 사용하십시오. – Lundin

답변

3

strncpy은 지정한 한도까지 데이터를 복사합니다. 그러나 문자열 끝에 도달하면 그 범위는 으로 변경되지 않고으로 끝납니다.

즉, strncpy에는 두 가지 가능성이 있습니다. 하나는 어쨌든 strcpy과 같은 동작을 얻게된다는 것입니다 (느린 것은 제외하고 NUL로 목적지 버퍼의 나머지 부분을 채 웁니다. 사실상 실제로는 원하지도 신경 쓰지도 않습니다). 다른 하나는 일반적으로 실제 사용할 수없는 결과를 산출한다는 것입니다.

는 고정 길이 버퍼에 최대 길이에 문자열을 복사 할 경우 (예를 들어) sprintf를 사용하는 작업을 수행 할 수 있습니다 strncpy 달리

char buffer[256]; 

sprintf(buffer, "%255s", source); 

, 항상이 을 결과를 제로 종료 (zero-terminate)하므로 결과는 항상 문자열로 사용 가능합니다.

당신이 sprintf (또는 유사)를 사용하지 않으려면, 그냥 실제로 당신이 일반적인 순서에 뭔가 원하는 것을 그 함수를 작성 좋을 걸 :

void copy_string(char const *dest, char const *source, size_t max_len) { 
    size_t i; 
    for (i=0; i<max_len-1 && source[i]; i++) 
     dest[i] = source[i]; 
    dest[i] = '\0'; 
} 

당신이 후로을 이 C++ (C 이외에) 태그 : 내 조언은 일반적으로 그냥이 std::string 사용하여 C++에서이 모든 엉망을 피할 것입니다.

당신이 정말로 C++에서 NUL 종료 순서로 작업해야하는 경우, 당신은 또 다른 가능성을 고려해 볼 수 있습니다 :

template <size_t N> 
void copy_string(char const (&dest)[N], char const *source) { 
    size_t i; 
    for (i=0; i<N-1 && source[i]; i++) 
     dest[i] = source[i]; 
    dest[i] = '\0'; 
} 

대상이 실제 배열 (안 포인터)는이 비로소 작동하지만에 대한 이 경우 사용자가 명시 적으로 전달해야하는 대신 컴파일러에서 배열의 크기를 추론합니다. 이것은 일반적으로 코드를 매우 빠르게 (함수 호출에서 오버 헤드가 적게) 빠르게 만들고 엉망으로 만들고 잘못된 크기를 전달하는 것이 훨씬 더 어렵습니다.

+1

당신도 수동으로 널 종결을 할 수 있습니다 :'strncpy (dest, source, size-1); dest [size] = '\ 0';'. 어쩌면 우아하지 않을 지 모르지만,'sprintf'보다 더 좋아할 것입니다. –

+1

@AndreiR .: 좋은 일반적인 포인트 (종종 끝났습니다),'dest [size]'? ;-) –

+0

@AndreiR .: 대안에 대한 답변이 추가되었습니다. –

2

strncpy을 사용하는 것에 대한 논쟁은 문자열이 null로 끝나야한다는 사실을 보장하지 않는다는 것입니다.

고정 길이가 아닌 배열을 사용할 때 C에서 문자열을 복사하는 경향이 적은 방법은 문자열의 null 종료를 보장하는 snprintf을 사용하는 것입니다.

좋은 Blog Post*n*의 기능에 댓글을 달기.

이러한 기능을 사용하면 버퍼 크기를 지정할 수 있지만 실제로는 중요하므로 null 종결을 보장하지는 않습니다. 이 함수들이 버퍼를 채울 문자보다 많은 문자를 쓰도록 요청하면 버퍼 오버런을 피할 수 있습니다. 그러나 버퍼를 널 종료하지 않습니다. 고정 된 배열을 처리하지 strncpy 및 기타 기능의 사용이 null 이외의 unnessisary 위험을 도입한다는 것을 의미

코드에서 시간 폭탄이 될 수있는 문자열을 종료했습니다.

+0

* "less error prone"* - 사실이지만 출력 결과를 제대로 확인하는 것은 여전히 ​​못 생겼습니다 :'int n = snprintf (buffer, sizeof buffer, "% s", source); assert (n> = 0 && n <버퍼의 크기);와'strncpy (buffer, source, sizeof buffer); assert (buffer [sizeof buffer-1] == '\ 0'); (가능한 경우 [strncpy'] (http : //en.cppreference.com/w/cpp/string/byte/strncpy)는 NUL로 전체 버퍼를 채 웁니다. –

+0

@TonyD 내가 생각하는 스타일의 문제? 나는 당신이 배열 액세스를하지 않기 때문에 개인적으로 첫 번째'assert'를 선호하며, 얼마나 많은 문자가 쓰여졌는지에 대한 접근 권한을 가지고있다. – Serdalis

+1

예 - 꽤 많은 스타일과 상황의 세부 사항 - 예 : 'n '을 잠재적으로 유용하게 대항하면 원하지 않는다면 지역 기호가 어지럽 혀서'n2','n3' 또는'o','p'를 빠르게하거나'this_len ','that_len' . –

0

char * strncpy (char * destination, const char * source, size_t num); strncpy에서의

제한() :

  1. 가 완전히 채워지면 그것은 대상 문자열에 널 (NULL) 종료를 두지 않습니다. 그리고 소스가 num보다 길면 목적지의 끝에 null 문자가 암시 적으로 추가되지 않습니다.
  2. num이 소스 문자열의 길이보다 큰 경우 대상 문자열에 num 길이까지의 null 문자가 채워집니다.

strcpy와 마찬가지로 메모리 안전 연산이 아닙니다. 원본을 복사하기 전에 대상에서 충분한 공간을 확인하지 않기 때문에 버퍼 오버런의 원인이 될 수 있습니다.

참조 : Why should you use strncpy instead of strcpy?

+0

특히 "stnncpy()"의 오리지널 문구를 사용하면 그 점과 첫 번째 점의 시작이 [이 답변] (http://stackoverflow.com/a/1258577/410767)에서 해제 된 것처럼 보입니다. 다른 곳에서 무언가를 사용한다면, 인용하고 속성을 지정하고 링크하십시오. 건배. –

+0

내 의견에이 링크를 언급했습니다. Btw, 이제는 내 대답에도 이것을 추가했습니다. 감사 !!! –

-1

우리는 고정 및 비 고정 길이 배열에 사용되는 또 다른 1> strcpy를 2>를 strncpy 이 두 버전 중 하나에서 복사 문자열 2 개 버전이 있습니다. strcpy는 문자열 복사시 대상 문자열의 상한선을 검사하지 않고, strncpy가 문자열을 검사합니다. 대상 문자열에이 상한에 도달하면 strncpy 함수는 오류 코드를 반환하고 strcpy 함수는 현재 프로세스의 메모리에 영향을 미치고 즉시 프로세스를 종료합니다. 그래서 strncpy는 strcpy보다 더 안전합니다

+0

'strncpy'는 오류 코드를 반환하지 않습니다. –