マルチスレッドのプログラミング

静的局所変数の利用

例 10-2 は、前述の errno と同様の問題を示すものです。ただし、ここでは広域的な記憶領域ではなく静的な記憶領域が問題となります。関数 gethostbyname(3N) は、コンピュータ名を引数として与えられて呼び出されます。その戻り値はある構造体のポインタで、その構造体には指定したコンピュータと、ネットワークを通して通信するために必要な情報が入っています。


例 10-2 gethostbyname() の問題


struct hostent *gethostbyname(char *name) {
    static struct hostent result;
        /* ホストデータベースから名前を検索 */
        /* result に答えを入れる */
    return(&result);
}

一般に、局所変数へのポインタを返すというのはよい方法ではありません。上記の例では、変数が静的なために正常に動作します。しかし、2 つのスレッドが異なるコンピュータ名で同時に関数を呼び出すと、静的記憶領域の衝突が生じます。

静的記憶領域の代わりに前述の errno のように、スレッド固有データを使用するという解決方法も考えられますが、動的記憶割り当てのため処理が重くなります。

このような問題を解決する方法は、gethostbyname() の呼び出し側が結果を戻すための記憶領域を呼び出し時に指定してしまうことです。具体的には、このルーチンに出力引数を 1 つ追加して、呼び出し側から与えます。そのためには、gethostbyname() に新しいインタフェースが必要です。

Solaris スレッドでは、この種の問題の多くを解決するために、上記のテクニックが使われています。通常、新しいインタフェース名は、末尾に「_r」を付けたものです。たとえば、gethostbyname(3N) は、gethostbyname_r(3N) となります。