8

sprintfスレッドセーフですか?

//Global log buffer 
char logBuffer[20];

logStatus (char * status, int length)
{
  snprintf(logBuffer, 19, status);
  printf ("%s\n", logBuffer);
}

snprintfこの関数のスレッドセーフは、 /のスレッドセーフに完全に依存しますsprintf

更新: urの回答に感謝します。実際の内容がめちゃくちゃになってもかまいません。しかし、複数のスレッドが書き込もうとしているときに、sprintfが20バイトを超えるメモリ破損/バッファオーバーフローを引き起こさないことを確認したいlogBufferですか?

4

7 に答える 7

16

snprintf()複数のスレッドで使用しても問題ありません。しかし、ここでは共有文字列バッファーに書き込んでいます。これはスレッド間で共有されていると思います。

したがって、この関数の使用はスレッドセーフではありません。

于 2012-11-14T20:00:25.887 に答える
3

コードにいくつか問題があります。

  1. の使用法snprintfは非常に疑わしいです。文字列をコピーするためだけに使用しないでください。通常、動的に割り当てられた文字列を、形式としてどのような内容でもprintf関数に渡さないでください。それらは内容を解釈し、%形式に似たものが含まれている場合、あなたは運命にあります。
  2. staticバッファを使用しないでください。これは確かにスレッドセーフでもリエントラントでもありません。
  3. 適切な形式で直接使用printfするか、呼び出しをに置き換えますputs

次に、LinuxはPOSIX標準に準拠します。この標準では、標準のIO関数がスレッドセーフである必要があります。

于 2012-11-14T20:46:10.007 に答える
3

snprintf()「複数のスレッドで使用しても問題ありません。」

違います。

少なくともPOSIX関数の場合は、正しくありません。

すべての標準vararg機能はmt-safeではありません-これにはすべてのprintf()ファミリが含まれます(1)だけでなく、他のすべてのvariadic機能も含まれます(2)

  1. sprintf()例:「MT-Safelocale | AS-Unsafe heap | AC-Unsafe mem」-これは、ロケールが非同期に設定されている場合、またはスレッドの非同期キャンセルが使用されている場合に失敗する可能性があることを意味します。つまり、MT環境でこのような機能を使用する場合は、特に注意が必要です。

  2. va_argmt-safeではありません:| MT-Safe race:ap | AS-Safe | AC-Unsafecorrupt | -つまり、インターロックが必要です。

さらに、当然のことながら、完全にmt-safe関数でさえ、安全でない方法で使用される可能性があります。たとえば、2つ以上のスレッドが同じデータ/メモリ領域を操作している場合はどうなりますか。

于 2015-06-03T22:05:39.380 に答える
2

あなたの質問は間違った前提を持っています。sprintf同時に複数のスレッドから安全に呼び出すことができる場合でも(確かにそうなることを願っています)、コードはグローバル変数を保護していません。標準ライブラリはおそらくあなたを助けることはできません。

于 2012-11-14T20:03:19.550 に答える
2

logBufferコンテンツが文字化けしても心配しないことについての更新について:

ローカルに割り当てられたバッファまたは同期メカニズムを使用して関数を完全にスレッドセーフにすることを避けたい理由はわかりませんが、POSIXがそれについて何を言っているのかを知りたい場合は、ここにアクセスします(http:// pubs .opengroup.org / onlinepubs / 9699919799 / basedefs / V1_chap04.html#tag_04_11):

アプリケーションは、複数の制御スレッド(スレッドまたはプロセス)による任意のメモリ位置へのアクセスが制限され、別の制御スレッドがメモリ位置を変更している間、制御スレッドがメモリ位置を読み取ったり変更したりできないようにする必要があります。このようなアクセスは、スレッドの実行を同期し、他のスレッドに関してメモリを同期する関数を使用して制限されます。[同期を提供する関数のリストが続きます]

したがって、POSIXによると、プログラムでは、複数のスレッドが同時に変更されないようにする必要がありますlogBuffer(または、あるスレッドで変更logBufferし、別のスレッドで読み取る必要があります)。あなたがそれに固執しなければ、起こるであろう最悪の事態がでのデータの文字化けであるという約束はありませんlogBuffer。結果がどうなるかについては、まったく約束がありません。Linuxがより具体的な動作を文書化できるかどうかはわかりませんが、文書化されているとは思えません。

于 2012-11-15T08:51:37.787 に答える
0

sprintfを使用するバッファはすべてのスレッド間で共有されるため、スレッドセーフではありません。

于 2012-11-14T20:16:32.107 に答える
0

「スレッドセーフではないという言及はありますか?私がグーグルで検索すると、スレッドセーフのようです」

この質問に対する私の以前の回答は削除/削除されたので(なぜ?)、別のアプローチを使用して再試行します:

  1. AC(スレッドの非同期キャンセル):これは明らかに、スレッドがランダムな時点で中断されたという理由だけで、「明らかにMTセーフ」なコードのほとんどすべてが失敗する可能性がある場合です。正しく動作する(つまり、どのような形式のミューテックスも正しく動作することを実際に保証することはできません)

  2. スレッドは同じmalloc()アリーナを使用できます。つまり、スレッドの1つが失敗した場合(つまり、mallocアリーナが破損した場合)、malloc()を連続して呼び出すと、重大なエラーが発生する可能性があります。これはもちろんです。システム構成によって異なりますが、これは、不正な形式のメモリ(脱)割り当てが安全であると誰も想定してはならないことも意味します。

すべてのシステムが異なるローカル設定を使用するオプションを提供しているため、非同期であることは明らかです。「ロケール」設定に変更すると、エラーが発生する可能性があります。

よろしく。

于 2017-07-15T22:42:11.587 に答える