TR 24731 の「安全な」機能を使用していますか?

私は、これらの TR が最初 (単一の TR だったとき) から声高に批判してきましたが、私のソフトウェアでそれらを使用することはありませんでした。それらは原因に対処する代わりに症状を覆い隠します。同じ目標をはるかに効果的に達成できる既存の慣行を促進する代わりに、誤った安心感を提供するため、どちらかといえばソフトウェア設計に悪影響を与えると私は考えています。私は一人ではありません。実際、これらの TR を策定する委員会以外に主要な支持者がいるとは知りません。

私は glibc を使用しているため、このナンセンスに対処する必要がなくなることを知っています。glibc のリード メンテナーである Ulrich Drepper がこのトピックについて次のように述べています。

彼は、提案された多くの関数の問題点を詳しく説明し、glibc がこれをサポートすることは決してないだろうと別の場所で指摘しています。

Austin Group (POSIX の維持を担当) は、TR の非常に批判的なレビュー、コメント、および委員会の回答を提供しました。 Austin Group のレビューは、TR に関する多くの問題を詳しく説明しているため、ここでは個別の詳細には触れません。

要するに、私はこれをサポートする、またはサポートする予定の実装を使用していません。これらの関数を使用する予定はありません。また、TR に正の値は見られません。個人的には、TR がどのような形であれ存続している唯一の理由は、広範な反対にもかかわらず、標準化委員会を通じて物事を突っ込む能力が非常に高いことを最近証明した Microsoft によって強く推し進められているからだと考えています。これらの関数が標準化されたとしても、提案が数年前から出回っており、実際のコミュニティのサポートを獲得できていないため、広く使用されることはないと思います.


質問に対する直接的な回答

Robert の回答は気に入っていますが、私が提起した質問についてもいくつかの見解があります。

    <リ>

    TR24731-1 関数をサポートするライブラリまたはコンパイラを使用していますか?

    <リ>

    もしそうなら、どのコンパイラまたはライブラリで、どのプラットフォームで?

    <リ>

    これらの関数を使用するようにコードを修正した結果、バグを発見しましたか?

    <リ>

    最も価値のある機能はどれですか?

    <リ>

    値がない、または負の値を提供するものはありますか?

    <リ>

    今後ライブラリを使用する予定はありますか?

    <リ>

    TR24731-2 の作業を追跡していますか?

全体として、パート 1 の「境界チェック インターフェイス」には納得できません。パート 2 'Dynamic Allocation Functions' の下書きの資料の方が優れています。

私に任せるなら、パート 1 の行に沿って移動しますが、char * を返す C99 標準 C ライブラリのインターフェイスも修正します。 文字列の先頭まで (例:strcpy() そして strcat() ) 最初へのポインターを返す代わりに、新しい文字列の末尾にある null バイトへのポインターを返すようにします。これにより、strcat() を繰り返し使用するコードによって示される 2 次動作を回避することが簡単になるため、いくつかの一般的なイディオム (文字列を別の文字列の末尾に繰り返し連結するなど) がより効率的になります。 . TR24731 バージョンのように、置換はすべて出力文字列のヌル終了を保証します。私は、インターフェイスのチェックや例外処理関数の考え方を完全に否定しているわけではありません。難しいビジネスです。

Microsoft の実装は標準仕様と同じではありません

更新 (2011-05-08)

この質問も参照してください。悲しいことに、TR24731 関数の有用性にとって致命的なことですが、一部の関数の定義は、Microsoft の実装と標準の間で異なり、(私にとっては)役に立たないものになっています。そこでの私の答えは vsnprintf_s() を引用しています .

同様に、scanf_s() にも問題があります。 とその親戚。 Microsoft によると、バッファ長パラメータの型は unsigned です (明示的に「サイズ パラメータの型は unsigned です」 、 size_t ではありません ')。対照的に、附属書 K では、サイズ パラメータは rsize_t 型です。 、これは size_t の制限されたバリアントです (rsize_t size_t の別名 、しかし RSIZE_MAX SIZE_MAX より小さい )。繰り返しになりますが、scanf_s() を呼び出すコードは Microsoft C と標準 C では、別の方法で記述する必要があります。

当初、条件付きコードを記述する必要なく、Windows と Unix でコードをクリーンにコンパイルする方法として、「安全な」関数を使用することを計画していました。 Microsoft と ISO の機能が常に同じであるとは限らないため、これは失敗に終わっているため、あきらめるにはかなり時間がかかります。

Microsoft の vsnprintf() の変更点 Visual Studio 2015 で

vsnprintf() の Visual Studio 2015 ドキュメント 、インターフェイスが変更されたことに注意してください:

ただし、vsnprintf_s() の Microsoft インターフェイスは 変更されていません。

Microsoft と Annex K の違いのその他の例

localtime_s() の C11 標準バリアント ISO/IEC 9899:2011 Annex K.3.8.2.4 で次のように定義されています。

struct tm *localtime_s(const time_t * restrict timer,
                       struct tm * restrict result);

localtime_s() の MSDN バリアントとの比較 定義:

errno_t localtime_s(struct tm* _tm, const time_t *time);

および POSIX バリアント localtime_r() 定義:

struct tm *localtime_r(const time_t *restrict timer,
                       struct tm *restrict result);

C11 標準と POSIX 関数は、名前を除いて同等です。 Microsoft 関数は、C11 標準と名前を共有していますが、インターフェイスが異なります。

違いのもう 1 つの例は、Microsoft の strtok_s() です。 附属書 K の strtok_s() :

char *strtok_s(char *strToken, const char *strDelimit, char **context); 

vs:

char *strtok_s(char * restrict s1, rsize_t * restrict s1max, const char * restrict s2, char ** restrict ptr);

Microsoft バリアントには 3 つの引数があるのに対し、Annex K バリアントには 4 つの引数があることに注意してください。これは、Microsoft の strtok_s() への引数リストが POSIX の strtok_r() と互換性があります — そのため、関数名を (マクロなどで) 変更した場合、これらの呼び出しは効果的に交換可能です — しかし、標準 C (Annex K) バージョンは、追加の引数で両方とは異なります。

質問 qsort_r() の異なる宣言 on Mac and Linux には、qsort_s() についても説明する回答があります。 Microsoft および qsort_s() によって定義されているとおり TR24731-1 で定義されているように — 繰り返しますが、インターフェースは異なります。

ISO/IEC 9899:2011 — C11 規格

C11 標準 (2010 年 12 月の草案。最終的な標準である ISO/IEC 9899:2011 の PDF コピーを ANSI Web ストアから 30 米ドルで一度に入手できます) には、TR24731-1 機能がオプションとして含まれています。規格の一部。それらは、「情報」ではなく「規範」である付属書 K (境界チェック インターフェース) で定義されていますが、オプションです。

C11 標準には TR24731-2 関数が含まれていません — vasprintf() function とその親戚は本当に便利です.

簡単な要約:

  • C11 には TR24731-1 が含まれています
  • C11 には TR24731-2 が含まれていません
  • C18 は TR24731 に関して C11 と同じです。

C11 の後継から附属書 K を削除する提案

Deduplicator は別の質問へのコメントで、ISO C 標準委員会 (ISO/IEC JTC1/SC22/WG14) の前に提案があることを指摘しました

  • N1967 附属書 K のフィールド エクスペリエンス — 境界チェック インターフェース

これには、附属書 K 関数の現存する実装の一部への参照が含まれています — それらはどれも広く使用されていません (ただし、興味がある場合はドキュメントから見つけることができます)。

ドキュメントは推奨事項で終わります:

したがって、Annex K を C 標準の次の改訂版から削除するか、非推奨にしてから削除することを提案します。

私はその勧告を支持します。

C18 標準は、附属書 K のステータスを変更しませんでした。附属書 K を完全に削除するのではなく、その欠陥を修復して、いくつかの変更を行うことを提唱する論文 N2336 があります。


わかりました、今度は の略です TR24731-2:

はい、asprintf() を使用しました /vasprintf() glibc でそれらを見て以来、私はそれらの非常に強力な支持者です.

なんで?
私が必要としているものを正確に提供してくれるからです。強力で、柔軟で、安全で、(比較的) 使いやすい方法で、任意のテキストを新たに割り当てられた文字列にフォーマットできます。

memstream にも大賛成です 関数:asprintf() のように 、 open_memstream() (fmemopen() ではありません !!!) 十分な大きさのバッファを割り当て、FILE* を返します 印刷を行うため、印刷関数は文字列に印刷するのかファイルに印刷するのかを完全に無視することができ、どのくらいのスペースが必要になるかを単純に忘れることができます.