例 9–2 は、errno と同様の問題を示します。ただし、ここでは大域的な記憶領域ではなく静的な記憶領域が問題となります。関数 gethostbyname(3NSL) は、コンピュータ名を引数として与えられて呼び出されます。その戻り値はある構造体のポインタで、その構造体には指定したコンピュータと、ネットワークを通して通信するために必要な情報が入っています。
struct hostent *gethostbyname(char *name) { static struct hostent result; /* Lookup name in hosts database */ /* Put answer in result */ return(&result); }
一般に、局所変数へのポインタを返すのはよい方法ではありません。この例では、変数が静的なため、ポインタは正常に動作します。しかし、2 つのスレッドが異なるコンピュータ名で同時に関数を呼び出すと、静的記憶領域の衝突が生じます。
静的記憶領域の代わりとして、errno の問題の場合と同様にスレッド固有データを使用できます。しかし、この方法では、動的に記憶領域が割り当てられるため、呼び出しの負荷が高くなります。
このような問題を解決する方法は、gethostbyname() の呼び出し側が結果を戻すための記憶領域を呼び出し時に指定してしまうことです。このルーチンに出力引数を 1 つ追加して、呼び出し側から記憶領域を提供できるようにします。出力引数を追加するには、gethostbyname() 関数に新しいインタフェースが必要です。
この方法は、上記のような問題の多くを解決するために使用されています。通常、新しいインタフェース名は、末尾に「_r」を付けたものです。たとえば、gethostbyname(3NSL) は、gethostbyname_r(3NSL) となります。