バッファオーバーランを回避するために、次のようにsnprintf
を使用しています。
char err_msg[32] = {0};
snprintf(err_msg, sizeof(err_msg) - 1, "[ ST_ENGINE_FAILED ]");
文字列の長さが32バイトを超える場合に備えて、ヌルターミネータ用のスペースを予約するために-1
を追加しました。
私の考えは正しいですか?
プラットホーム:
他の人が言っているように、この場合は-1は必要ありません。配列が固定サイズの場合、代わりにstrncpy
を使用します。文字列をコピーするために作成されました-sprintf
は難しいフォーマットを行うために作成されました。ただし、配列のサイズが不明な場合、またはフォーマットされた文字列に必要なストレージの量を決定しようとしている場合。これは、私がsnprintf
の標準指定バージョンについて本当に気に入っていることです。
char* get_error_message(char const *msg) {
size_t needed = snprintf(NULL, 0, "%s: %s (%d)", msg, strerror(errno), errno);
char *buffer = malloc(needed+1);
sprintf(buffer, "%s: %s (%d)", msg, strerror(errno), errno);
return buffer;
}
この機能をva_copy
と組み合わせると、非常に安全なフォーマットされた文字列操作を作成できます。
参照にあるように、-1は必要ありません。
関数snprintf()およびvsnprintf()は、サイズバイト(末尾の「\ 0」を含む)を超えて書き込みません。
「末尾の「\ 0」を含む」の部分に注意してください
-1は必要ありません。 C99 snprintf
常にゼロで終了します。サイズ引数は、出力バッファのサイズを指定します含むゼロターミネータ。したがって、コードは次のようになります。
char err_msg[32];
int ret = snprintf(err_msg, sizeof err_msg, "[ ST_ENGINE_FAILED ]");
ret
には、実際に印刷された文字数が含まれます(除外ゼロターミネータ)。
ただし、Microsoftの _snprintf
(pre-C99)と混同しないでください。これはnotnull-terminateを実行します。そして、そのことについては、完全に異なる動作をします(たとえば、バッファが十分に大きくない場合に印刷される長さの代わりに-1
を返す)。 _snprintf
を使用する場合は、質問と同じコードを使用する必要があります。
snprintf(3)
によると:
関数
snprintf()
およびvsnprintf()
は、size
バイト(末尾の'\0'
を含む)を超えて書き込みません。
与えられた例では、代わりにこれを行う必要があります。
char err_msg[32];
strncpy(err_msg, "[ ST_ENGINE_FAILED ]", sizeof(err_msg));
err_msg[sizeof(err_msg) - 1] = '\0';
またはさらに良い:
char err_msg[32] = "[ ST_ENGINE_FAILED ]";