次の簡単な C プログラムを考えてみましょう。
#include <errno.h>
int
main(int argc, char* argv[]) {
return errno;
}
Solaris でコンパイルした場合、このコードの動作は の存在に依存し-D_REENTRANT
ます。
solaris$ cc -E test.c | grep return
return errno;
solaris$ cc -D_REENTRANT -E test.c | grep return
return ( * ( ___errno ( ) ) );
後者のバージョンはスレッドセーフです。Linux で同じコードをコンパイルすると、同じ動作が得られます。-D_REENTRANT
linux$ gcc -E test.c | grep return
return (*__errno_location ());
linux$ gcc -D_REENTRANT -E test.c | grep return
return (*__errno_location ());
Solaris'cc
にはオプションがあり、これは'sと同様-mt
に を意味します。ただし、ライブラリの場合、これらのマルチスレッド オプションを指定すると、スレッド ランタイムに不要な依存関係が挿入されるため、不十分に思えます。ただし、ライブラリをスレッドセーフ (errno を含む) にする必要がある場合は、ライブラリのコンパイル時と派生コードの両方でスレッドセーフなセマンティクスが必要です。Linux では、errno は常にスレッド ローカルであるため、これは簡単ですが、上記で示したように、他のシステムでは保証されません。-D_REENTRANT
gcc
-pthread
その結果、スレッド セーフなライブラリを適切にコンパイルし、ヘッダーを付けて配布するにはどうすればよいかという疑問が生じます。1 つのオプションは#define _REENTRANT
、メイン ヘッダー内にあることですが、これが#include <errno.h>
ライブラリ ヘッダーのインクルードの前に発生すると、問題が発生します。別のオプションは、ライブラリを でコンパイルし、が定義されていない場合は-D_REENTRANT
メイン ヘッダーを持つことです。#error
_REENTRANT
スレッドセーフなライブラリを作成し、リンクされているコードと正しく相互運用できるようにするための正しい/最良の方法は何ですか?