development

snprintf ()는 항상 null로 종료됩니까?

big-blog 2020. 10. 27. 22:45
반응형

snprintf ()는 항상 null로 종료됩니까?


snprintf는 항상 대상 버퍼를 종료하는 null입니까?

즉, 이것으로 충분합니까?

char dst[10];

snprintf(dst, sizeof (dst), "blah %s", somestr);

아니면 somestr이 충분히 길다면 이렇게해야합니까?

char dst[10];

somestr[sizeof (dst) - 1] = '\0';
snprintf(dst, sizeof (dst) - 1, "blah %s", somestr);

나는 표준이 말하는 것과 표준 동작이 아닌 일부 대중적인 libc가 무엇을 할 수 있는지에 관심이 있습니다.


다른 답변이 설정으로 : 그것은 해야한다 :

snprintf... 결과를 문자열 버퍼에 기록합니다. (...) buf_size가 0이 아니면 널 문자로 종료됩니다.

따라서주의해야 할 것은 크기가 0 인 버퍼를 전달하지 않는 것입니다. 왜냐하면 (분명히) "nowhere"에 0을 쓸 수 없기 때문입니다.


그러나 조심 마이크로 소프트의 라이브러리가 없는 라는 함수를 대신 역사적으로 단지 라는 함수했다 (참고 선도 밑줄) 추가하지 않습니다 종단 널 (null)입니다. 다음은 문서입니다 (VS 2012, ~~ VS 2013) : snprintf_snprintf

http://msdn.microsoft.com/en-us/library/2ts7cx93%28v=vs.110%29.aspx

반환 값

len을 형식화 된 데이터 문자열의 길이 (종료 널을 포함하지 않음)로 지정하십시오. len 및 count는 _snprintf의 경우 바이트, _snwprintf의 경우 와이드 문자입니다.

  • len <count이면 len 문자가 버퍼에 저장되고 널 종료자가 추가되며 len이 리턴됩니다.

  • len = count이면 len 문자가 버퍼에 저장되고 널 종료자가 추가되지 않으며 len이 리턴됩니다.

  • len> count이면 count 문자가 버퍼에 저장되고 null 종료자가 추가되지 않고 음수 값이 반환됩니다.

(...)

Visual Studio 2015 (VC14)는 준수 snprintf기능을 도입 한 것으로 보이지만 선행 밑줄이 있고 null 아닌 종료 동작이 있는 레거시 기능 이 여전히 있습니다.

snprintf함수는 len이 count보다 크거나 같을 때 null 종결자를에 배치하여 출력을 자릅니다 buffer[count-1]. (...)

모든 함수 다른 보다 snprintfLEN = 카운트 경우 len 문자가 버퍼에 저장되며, 어떤 널 종결이 추가되지 않는다 (...)


snprintf (3) 맨 페이지에 따름.

함수 snprintf()vsnprintf()최대 size바이트 (후행 널 바이트 ( '\ 0') 포함)를 str.

따라서 크기가 1보다 크면 종료 할 필요가 없습니다.


버퍼 크기는 0, C 않는 표준에 따르면, vsnprintf()snprintf()널 (null)의 출력을 종료한다.

snprintf()함수에 상당한다 sprintf()버퍼의 크기 (S)로 지칭 상태 n 인수의 추가. n이 0이면 아무것도 기록되지 않고 s는 널 포인터가 될 수 있습니다. 그렇지 않으면 n-1st 이후의 출력 바이트는 배열에 기록되는 대신 폐기되고 실제로 배열에 기록 된 바이트의 끝에 널 바이트가 기록됩니다.

따라서 할당 할 버퍼의 크기를 알아야하는 경우 0 크기를 사용하고 널 포인터를 대상으로 사용할 수 있습니다. 내가 POSIX 페이지에 링크했지만, 이는 표준 C와 POSIX가 동일한 영역을 다루는 곳에서 차이가 발생하지 않는다고 명시 적으로 말합니다.

이 참조 페이지에 설명 된 기능은 ISO C 표준과 일치합니다. 여기에 설명 된 요구 사항과 ISO C 표준 간의 충돌은 의도하지 않은 것입니다. POSIX.1-2008의이 볼륨은 ISO C 표준을 따릅니다.

Microsoft 버전의 vsnprintf(). 버퍼에 충분한 공간이 없을 때 표준 C 버전과 확실히 다르게 작동합니다 (표준 함수가 필요한 길이를 반환하는 경우 -1을 반환합니다). 표준 C 버전이 수행하는 반면 Microsoft 버전 null이 오류 조건에서 출력을 종료한다는 것은 명확하지 않습니다.

TR 24731 안전 기능을 사용합니까?에 대한 답변도 참고하십시오 . ( 의 Microsoft 버전 MSDN 참조 vsprintf_s()) 및 안전하지 않은 C 표준 라이브러리 함수에 대한 안전한 대안은 Mac 솔루션입니까?


일부 이전 버전의 SunOS는 snprintf로 이상한 일을했고 출력을 NUL로 종료하지 않았을 수 있고 다른 사람들이하는 일과 일치하지 않는 반환 값을 가지고 있었지만 지난 10 년 동안 릴리스 된 모든 것은 C99를 수행했습니다. 말한다.


모호성은 C 표준 자체에서 시작됩니다. C99와 C11은 모두 동일한 snprintf기능 설명을 갖습니다 . 다음은 C99의 설명입니다.

7.19.6.5 snprintf함수
개요
1 #include <stdio.h> int snprintf(char * restrict s, size_t n, const char * restrict format, ...);
설명
2 출력이 스트림이 아닌 배열 (인수로 지정됨)에 기록된다는 점을 제외하면 함수 는와snprintf 동일 합니다. 경우 IS는 제로, 아무것도 기록되지 않고, 널 포인터가 될 수있다. 그렇지 않으면 st를 초과하는 출력 문자 는 배열에 기록되지 않고 버려지고 실제로 배열에 기록 된 문자의 끝에 널 문자가 기록됩니다. 겹치는 객체간에 복사가 발생하면 동작이 정의되지 않습니다. 반환 3 함수를 작성했다되었을 것입니다 문자 수를 반환fprintfsnsn-1

snprintfn종료 널 문자를 계산하지 않거나 인코딩 오류가 발생한 경우 음수 값을 계산하지 않고 충분히 커야합니다. 따라서 반환 된 값이 음수가 아니고보다 작은 경우에만 null로 끝나는 출력이 완전히 기록되었습니다 n.

한편 으로 문장

그렇지 않으면 st를 초과하는 출력 문자n-1 는 배열에 기록되지 않고 버려지고 실제로 배열에 기록문자의 끝에 널 문자가 기록됩니다.

says that
if (the s points to a 3-character-long array, and) n is 3, then 2 characters will be written, and the characters beyond the 2nd one are discarded; then the null character is written after those 2 (and the null character will be the 3rd character written).

And this I believe answers the original question.
THE ANSWER:
If copying takes place between objects that overlap, the behavior is undefined.
If n is 0 then nothing is written to the output
otherwise, if no encoding errors encountered, the output is ALWAYS null-terminated (regardless of whether the output fits in the output array or not; if not then some characters are discarded such that the output array is never overflown),
otherwise (if encoding errors are encountered) the output can stay non-null-terminated.

On the other hand
The last sentence

Thus, the null-terminated output has been completely written if and only if the returned value is nonnegative and less than n

gives ambiguity (or my English is not good enough). I can interpret this sentence in at least two ways:
1. The output is null-terminated if and only if the returned value is nonnegative and less than n (which means that if the returned value is not less than n, i.e. the output (including the terminating null character) does not fit in the array, then the output is not null-terminated).
2. The output is complete (no characters have been discarded) if and only if the returned value is nonnegative and less than n.


I believe that the interpretation 1 above contradicts THE ANSWER, causes misunderstanding and lengthy discussions. That is why the last sentence describing the snprintf function needs a change in order to remove any ambiguity (which gives grounds for writing a Proposal to the C language Standard).
The example of non-ambiguous wording I believe can be taken from http://en.cppreference.com/w/c/io/fprintf (see 4)), thanks to @"Martin Ba" for the link.

See also the question "snprintf: Are there any C Standard Proposals/plans to change the description of this func?".

참고URL : https://stackoverflow.com/questions/7706936/is-snprintf-always-null-terminating

반응형