问题
I found that strncpy_s()
is defined under VS2013 as
errno_t __cdecl strncpy_s
(
_Out_writes_z_(_SizeInBytes) char * _Dst,
_In_ rsize_t _SizeInBytes,
_In_reads_or_z_(_MaxCount) const char * _Src,
_In_ rsize_t _MaxCount
);
rsize_t
is:
typedef size_t rsize_t;
I think it's a trick done by Visual Studio. However, I found this function defined as follows on this page
errno_t strncpy_s
(
char *restrict dest,
rsize_t destsz,
const char *restrict src,
rsize_t count
);
Why is rsize_t
defined here?
What if size_t
was used here?
Any special cases to use this rsize_t
?
回答1:
You've encountered it in Microsoft's C++ standard library, but it actually comes from C. C 11, to be precise, which means it's not technically a part of C++.
C 11 standard, Annex K introduced all the _s
functions and the corresponding typedefs, including rsize_t
. There is also a "maximum value" macro RSIZE_MAX
which is large enough for typical applications, but smaller than the real maximum value of the type. The secure functions do nothing and report an error when a value of type rsize_t
exceeds RSIZE_MAX
.
The idea is to avoid crashes on buffer overruns and similar errors caused by invalid sizes, usually resulting from using a negative value for size. In 2's complement signed value representation (the most common one), a negative number corresponds to a very large number when treated as unsigned. RSIZE_MAX
should catch such incorrect use.
Quoting the "rationale" part of C11 (N1570), K.3.2:
3 Extremely large object sizes are frequently a sign that an object’s size was calculated incorrectly. For example, negative numbers appear as very large positive numbers when converted to an unsigned type like
size_t
. Also, some implementations do not support objects as large as the maximum value that can be represented by typesize_t
.4 For those reasons, it is sometimes beneficial to restrict the range of object sizes to detect programming errors. For implementations targeting machines with large address spaces, it is recommended that
RSIZE_MAX
be defined as the smaller of the size of the largest object supported or(SIZE_MAX >> 1)
, even if this limit is smaller than the size of some legitimate, but very large, objects. Implementations targeting machines with small address spaces may wish to defineRSIZE_MAX
asSIZE_MAX
, which means that there is no object size that is considered a runtime-constraint violation.
It is worth noting that Annex K has very few implementations and there is a proposal (N1967) to deprecate and/or remove it from the standard.
回答2:
These typedefs have semantic meaning. Obviously you can use size_t
here (since it's the same), but rsize_t
is more verbose:
The type size_t generally covers the entire address space. ISO/IEC TR 24731-1-2007 introduces a new type rsize_t, defined to be size_t but explicitly used to hold the size of a single object. [1]
It's the similar situation as when using size_t
instead of unsigned int
. It's basically the same, but named differently so it's easy for you to understand what you're working with (size_t
= "size of something", which implies an unsigned whole number).
It is worth noting (as suggested by the comments) that rsize_t
is defined in the C specification, but not in the C++ specification.
来源:https://stackoverflow.com/questions/33604857/why-is-rsize-t-defined