为什么要定义 rsize_t?

Why is rsize_t defined?

我发现strncpy_s()VS2013下定义为

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 是:

typedef size_t rsize_t;

我认为这是 Visual Studio 搞的把戏。但是,我发现这个函数定义如下 page

errno_t strncpy_s
(
  char *restrict dest,
  rsize_t destsz,
  const char *restrict src, 
  rsize_t count
); 

这里为什么要定义rsize_t

如果这里使用了size_t呢?

有什么特殊情况可以使用这个rsize_t

这些类型定义具有语义。显然你可以在这里使用 size_t(因为它是一样的),但是 rsize_t 更冗长:

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]

这与使用 size_t 而不是 unsigned int 时的情况类似。它基本相同,但命名不同,因此您很容易理解您正在使用的是什么(size_t = "size of something",这意味着一个无符号整数)。

值得注意的是(如评论所建议的)rsize_t 在 C 规范中定义,但在 C++ 规范中没有定义。

你在微软的 C++ 标准库中遇到过它,但它实际上来自 C. C 11,准确地说,这意味着它在技术上不是 C++ 的一部分。

C 11 标准,附件 K 介绍了所有 _s 函数和相应的类型定义,包括 rsize_t。还有一个"maximum value"宏RSIZE_MAX,它对于典型的应用来说足够大,但小于该类型的实际最大值。当 rsize_t 类型的值超过 RSIZE_MAX.

时,安全函数什么都不做并报告错误

这个想法是为了避免因缓冲区溢出和无效大小导致的类似错误而崩溃,这些错误通常是由于大小使用负值造成的。在 2 的补码有符号值表示法(最常见的一种)中,负数对应于 非常 的大数(当被视为无符号数时)。 RSIZE_MAX 应该抓住这种不正确的用法。

引用 C11 (N1570) 的 "rationale" 部分,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 type size_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 define RSIZE_MAX as SIZE_MAX, which means that there is no object size that is considered a runtime-constraint violation.


值得注意的是,Annex K 的实现很少,并且有一项提案(N1967)弃用and/or 将其从标准中删除。