web-dev-qa-db-ja.com

なぜrsize_tが定義されているのですか?

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

23
zangw

これはMicrosoftのC++標準ライブラリで発生しましたが、実際にはC. C 11に由来しています。つまり、厳密にはC++の一部ではありません。

C 11標準、Annex Kは、_sを含むすべてのrsize_t関数と対応するtypedefを導入しました。 「最大値」マクロRSIZE_MAXもあります。これは、一般的なアプリケーションには十分な大きさですが、型の実際の最大値よりも小さいです。セキュア関数は、タイプrsize_tの値がRSIZE_MAXを超えると何もせず、エラーを報告します。

アイデアは、通常、サイズに負の値を使用したために発生する、無効なサイズによって引き起こされるバッファオーバーランおよび同様のエラーによるクラッシュを回避することです。 2の補数の符号付き値表現(最も一般的なもの)では、負の数は符号なしとして扱われる場合、very大きな数に対応します。 RSIZE_MAXは、このような誤った使用をキャッチする必要があります。

C11(N1570)、K.3.2の「根拠」部分を引用すると、

3非常に大きいオブジェクトサイズは、多くの場合、オブジェクトのサイズが正しく計算されなかったことを示しています。たとえば、負の数は、size_tのような符号なしの型に変換すると、非常に大きな正の数として表示されます。また、一部の実装は、タイプsize_tで表すことができる最大値と同じ大きさのオブジェクトをサポートしていません。

4これらの理由により、プログラミングエラーを検出するためにオブジェクトサイズの範囲を制限することが有益な場合があります。大きなアドレス空間を持つマシンをターゲットとする実装では、RSIZE_MAXを、サポートされる最大のオブジェクトのサイズまたは(SIZE_MAX >> 1)の小さい方として定義することをお勧めします。この制限が正当なサイズよりも小さい場合でも、しかし非常に大きなオブジェクト。小さなアドレススペースを持つマシンをターゲットとする実装では、RSIZE_MAXSIZE_MAXとして定義する必要がある場合があります。これは、実行時制約違反と見なされるオブジェクトサイズがないことを意味します。


Annex Kの実装は非常に少なく、非推奨にしたり、標準から削除したりする提案( N1967 )があることは注目に値します。

これらのtypedefには意味的な意味があります。明らかにここではsize_tを使用できます(同じなので)rsize_tの方が冗長です:

タイプsize_tは通常、アドレス空間全体をカバーします。 ISO/IEC TR 24731-1-2007では、rsize_tという新しいタイプが導入されました。これは、size_tとして定義されていますが、1つのオブジェクトのサイズを保持するために明示的に使用されています。 [1]

size_tの代わりにunsigned intを使用する場合と同様の状況です。基本的には同じですが、名前が異なるので、作業内容を簡単に理解できます(size_t = "何かのサイズ"。これは、符号なし整数を意味します)。

(コメントで示唆されているように)rsize_tはC仕様で定義されていますが、C++仕様では定義されていないことに注意してください。

13
SingerOfTheFall