localtime
(歴史的に) 静的バッファーへのポインターを返す C 標準ライブラリーのような関数を考えてみましょう。C11 はこれらのバッファをスレッドローカルにしますか?
C11 の 7.1.4 あたり:
以下の詳細な説明で特に明記されていない限り、ライブラリ関数は次のようにデータ競合を防止するものとします: オブジェクトが関数の引数を介して直接または間接的にアクセスされない限り、ライブラリ関数は現在のスレッド以外のスレッドによってアクセス可能なオブジェクトに直接または間接的にアクセスしてはなりません。 . オブジェクトが関数の非 const 引数を介して直接的または間接的にアクセスされない限り、ライブラリ関数は、現在のスレッド以外のスレッドによってアクセス可能なオブジェクトを直接的または間接的に変更してはなりません。オブジェクトがユーザーに表示されず、データ競合から保護されている場合、実装はスレッド間で独自の内部オブジェクトを共有できます。
例を考えてみましょうlocaltime
。struct tm
戻り値が指す は、呼び出し元がアクセスできるため、「内部オブジェクト」とは見なされないようです。そのため、別のスレッドで を呼び出しても、localtime
最初のスレッドで以前に返された結果が失われることはないようです。localtime
これは、スレッドごとに異なるバッファを使用する必要があることを意味します。
struct tm
ただし、アドレスが返されるオブジェクトの有効期間の終わりを標準が指定している場所はどこにもありません。呼び出し元のスレッドが終了した後もこれを使用し続けるプログラムが無効になる理由はわかりません。したがって、オブジェクトにスレッド ストレージ期間を指定することはできません。
実装がすべての要件を満たすことができることを確認できる唯一の方法は、いたるところでメモリをリークすることです。これは意図したことではありません。私は明らかな何かを見逃していますか、それともC11のレガシーインターフェースに関するスレッドセーフの扱いは本当に考え抜かれていますか?