[c] 왜 strcpy 대신 strncpy를 사용해야합니까?

편집 : 예제에 대한 소스를 추가했습니다.

내가 건너 온 이 예 :

이 출력은 다음과 같습니다.

목적지는 원래 = 'abcdefg'
strcpy 이후 목적지는 '123456789'가됩니다.

destination1은 원래 = 'abcdefg'입니다.
strncpy 이후 destination1은 '12345fg'가됩니다.

왜 누군가가이 효과를 원하는지 궁금합니다. 혼란 스러울 것 같습니다. 이 프로그램은 기본적으로 Tom Bro763을 사용하여 누군가의 이름 (예 : Tom Brokaw)을 복사 할 수 있다고 생각하게합니다.

strncpy() over 사용의 장점은 무엇입니까strcpy() ?



답변

strncpy길이를 입력하도록 요구하여 버퍼 오버 플로우를 방지합니다. strcpy후행에 의존하며 \0항상 발생하지는 않습니다.

둘째, 7 자 문자열에 5 자만 복사하도록 선택한 이유는 저를 넘어서지 만 예상되는 동작을 생성합니다. 세 번째 인수가 있는 첫 번째 n문자 만 복사합니다 n.

n함수는 모두 버퍼 오버플로에 대한 방어 코딩으로 사용됩니다. 와 같은 이전 기능 대신 사용하십시오 strcpy.


답변

strncpy()함수는 매우 특별한 문제를 염두에두고 설계되었습니다. 원래 UNIX 디렉토리 항목의 방식으로 저장된 문자열을 조작하는 것입니다. 이것들은 고정 된 크기의 배열을 사용했고, nul- 종결자는 파일 이름이 배열보다 짧은 경우에만 사용되었습니다.

이것이 두 가지 이상한 이유 뒤에 있습니다 strncpy().

  • 완전히 채워지면 대상에 Nul- 종결자를 넣지 않습니다. 과
  • 항상 목적지를 완전히 채우고 필요한 경우 nuls로 채 웁니다.

“안전한 strcpy()“경우 다음 strncat()과 같이 사용하는 것이 좋습니다 .

그것은 항상 결과를 무효화하고 필요 이상으로 복사하지 않을 것입니다.


답변

의 의도를 알고 있지만 strncpy실제로 좋은 기능은 아닙니다. 둘 다 피하십시오. Raymond Chen이 설명합니다 .

개인적으로 내 결론은 단순히 strncpynull로 끝나는 문자열을 다루는 경우 모든 친구들 을 피하는 것 입니다. 이름에 “str”이 있음에도 불구하고 이러한 함수는 null로 끝나는 문자열을 생성하지 않습니다. 널로 끝나는 문자열을 원시 문자 버퍼로 변환합니다. 두 번째 버퍼가 잘못되어 널로 끝나는 문자열이 예상되는 곳에서 사용합니다. 소스가 너무 길면 적절한 null 종료를 얻지 못할뿐만 아니라 소스가 짧으면 불필요한 null 패딩이 발생합니다.

strncpy가 안전하지 않은 이유 도 참조하십시오 .


답변

strncpy는 strcpy보다 안전하지 않으며 한 유형의 버그를 다른 유형과 교환 할뿐입니다. C에서 C 문자열을 처리 할 때 버퍼의 크기를 알아야합니다. strncpy는 다른 사람들이 언급 한 디렉토리 항목에 대해 정당화되었지만 그렇지 않으면 절대 사용해서는 안됩니다.

  • 문자열과 버퍼의 길이를 알고 있다면 왜 strncpy를 사용합니까? 기껏해야 컴퓨팅 능력의 낭비입니다 (쓸모없는 0 추가).
  • 길이를 모르면 버퍼 오버플로보다 낫지 않은 문자열을 조용히 잘라낼 위험이 있습니다.


답변

당신이 찾고 strlcpy()있는 것은 항상 0으로 문자열을 종료하고 버퍼를 초기화하는 함수 입니다. 또한 오버플로를 감지 할 수 있습니다. 유일한 문제는 (정말) 이식성이없고 일부 시스템 (BSD, Solaris)에만 존재한다는 것입니다. 이 기능의 문제점은 http://en.wikipedia.org/wiki/Strlcpy 의 토론에서 볼 수 있듯이 또 다른 웜 캔을 열 수 있다는 것입니다
.

제 개인적인 의견은 strncpy()및 보다 훨씬 더 유용하다는 것 strcpy()입니다. 더 나은 성능을 가지고 있으며 snprintf(). 이 기능이없는 플랫폼의 경우 구현하기가 비교적 쉽습니다. (응용 프로그램의 개발 단계에서는이 두 함수 ( snprintf()strlcpy())를 버퍼 오버플로 또는 잘림시 프로그램을 잔인하게 중단하는 트 랩핑 버전으로 대체합니다 . 이렇게하면 최악의 공격자를 신속하게 잡을 수 있습니다. 특히 다른 사람의 코드베이스에서 작업하는 경우 .

편집 : strlcpy()쉽게 구현할 수 있습니다.


답변

strncpy()함수는 더 안전한 함수입니다. 대상 버퍼가 허용 할 수있는 최대 길이를 전달해야합니다. 그렇지 않으면 소스 문자열이 올바르게 0으로 종료되지 않을 strcpy()수 있습니다. 이 경우 함수는 대상에 더 많은 문자를 기록하여 대상 버퍼 이후의 메모리에있는 모든 것을 손상시킬 수 있습니다. 이것은 많은 익스플로잇에서 사용되는 버퍼 오버런 문제입니다.

또한 read()버퍼에 종료 0을 넣지 않고 읽은 바이트 수를 반환하는 POSIX API 함수의 경우 수동으로 0을 넣거나 strncpy().

예제 코드에서는 index실제로 인덱스가 아니지만 counta- 소스에서 대상으로 복사 할 문자 수 를 나타 냅니다. 소스의 처음 n 바이트 중 널 바이트가없는 경우 대상에 배치 된 문자열은 널로 종료되지 않습니다.


답변

strncpy는 목적지의 크기가 더 작더라도 소스의 크기에 대해 ‘\ 0’으로 목적지를 채 웁니다 ….

맨 페이지 :

src의 길이가 n보다 작 으면 strncpy ()는 dest의 나머지 부분을 널 바이트로 채 웁니다.

나머지뿐만 아니라 …이 후 n 문자에 도달 할 때까지. 따라서 오버플로가 발생합니다 … (맨 페이지 구현 참조)