8

以前に作成したコードを調べていて、StringCbPrintf()関数を見つけました

msdn私はこのようなサイトで宣言を見つけました:

HRESULT StringCbPrintf(
  _Out_  LPTSTR pszDest,
  _In_   size_t cbDest,
  _In_   LPCTSTR pszFormat,
  _In_    ...
);

_in_こことは何_out_ですか?

そして、私たちがすでに持っているのになぜそれが必要なのsprintf()ですか?

4

3 に答える 3

9

_In_および_Out__in_/_outあなたが書いたように_も、__In__/__Out__他の回答で書かれたように二重アンダースコアも付けない)は、いわゆるSAL注釈です。これらは/analyzeコンパイラオプションとともに使用でき、生のCバッファとポインタでのバッファオーバーランなどのバグや問題を特定するのに役立ちます。SALに関するMSDNドキュメントに加えて、このブログ投稿も読むことができます。

皮肉なことに(そして間違って)誰かがそれを書いた:

「他の世界では、入力はconstポインターですが、それは単純すぎると思います。:)」

SALがそれよりも強力であるという事実を見逃しています。実際、SALを使用すると、宛先バッファーの最大サイズを指定して、宛先バッファーのサイズが含まれているパラメーターを指定することもできます。たとえば、ヘッダーを開くと、 (のUnicodeバージョン)に<strsafe.h>使用される実際のSALアノテーションは次のようになっていることがわかります。StringCbPrintfWStringCbPrintf

STRSAFEAPI
StringCbPrintfW(
    __out_bcount(cbDest) STRSAFE_LPWSTR pszDest,
    __in size_t cbDest,
    __in __format_string STRSAFE_LPCWSTR pszFormat,
    ...)
{
    ....

__out_bcount(cbDest)パラメーターに適用されたSALアノテーションが、これが出力バッファー()pszDestへのポインターであることをどのように指定しているかに注意してください。サイズはパラメーターによってバイト()で表されます。ご覧のとおり、これは豊富な注釈です(単純な「」または「非」よりも豊富です)。__out_bcountcbDestconstconst

私の意見では、SALは、独自のサイズなどを知っている、などの堅牢なコンテナクラスを使用してC ++コードを作成する場合は役に立たないです。しかし、SALは、生のポインタを使用するC風のコード(いくつかのWin32 APIなど)で役立ちstd::vectorます。std::string

あなたの質問の2番目の部分について:

StringCbPrintf「すでに持っているのになぜ必要なのかsprintf

主な理由はsprintf安全ではなく、バッファオーバーランが発生しやすい関数であるということです。代わりにStringCbPrintf、宛先バッファの最大サイズを指定する必要があります。これにより、バッファオーバーラン(セキュリティの敵)を防ぐことができます。

于 2012-11-07T14:28:12.437 に答える
3

ドキュメントはあなたのためにそれを説明しようとします:

置き換えられる関数と比較して、StringCbPrintfは、コードで適切なバッファー処理を行うための追加の処理を提供します。不十分なバッファ処理は、バッファオーバーランを含む多くのセキュリティ問題に関係しています。StringCbPrintfは、長さがゼロ以外の宛先バッファーを常にnullで終了します。

およびデコレータは__In____Out__Microsoft APIで使用され、ポインタ引数の使用方法を示します。他の世界では、入力はconstポインターですが、それは単純すぎたと思います。:)

于 2012-11-07T11:50:34.450 に答える
2

ここで言われているように:

StringCbPrintfは、次の関数の代わりになります。

  • sprintf、swprintf、_stprintf
  • wsprintf
  • wnsprintf
  • _snprintf、_snwprintf、_sntprintf

したがって、これは、を置き換えるだけでなく、たとえば、使用sprintfするものも置き換えます。wcharまた、バッファオーバーランを防ぐための追加のバッファ処理も導入されています(同じmsdnの記事に記載されています)。また、宛先バッファを常にnullで終了します。_in_どのパラメーターが入力パラメーターで、どのパラメーターが出力パラメーターで_out_あるかを示すためにあります。それらはおそらく#define何もないとしてdであり、コンパイルが始まる前に消えます。

于 2012-11-07T11:51:26.780 に答える