質問: ライブラリ作成時のグローバル変数の対応(c言語) c言語を用いてライブラリを作成しています。 ライブラリは機能ごとにファイルを分けています。 今、ライブラリの中でのみ使用するグローバル変数やグローバル関数が必要になりました。 このグローバル変数や関数は複数ファイルで参照するため、static宣言はできません。 しかし、このグローバル変数や関数は公開する必要はありません(ライブラリの中でのみ使用します)。 このようなことをc言語で実現するためにはどうしたらよいのでしょうか? 開発環境は windows7 visualc++2010 です。 visualc++2010を使うなら c++で書けばいいのではないかといわれそうですが、 c言語でプログラミングしたいのです。 以下のようなサイトがあったのですが、これを使うしかないでしょうか? http://0xcc.net/blog/archives/000108.html
回答: スレッドセーフを意識する場合、ライブラリ内でグローバル変数を持つ事は許されません。 「一連の呼び出しの中で、グローバルなスコープが必要」なのであれば、fopen関数でやっているように「開始関数で一意のハンドラを返し、一意のハンドラを指定して一連の呼び出しを行ってもらい、終了処理で一意のハンドラを開放する」と言うような書き方をしないといけません。 fopenが「グローバル変数で、次に使える、空いているハンドラの番号を持っている」と言う実装があったとします。 もし、メインのスレッドでfopenが3番のハンドラを返そうと準備している真っ最中(fopenから、まだ帰って来てない状態)に、サブのスレッドがfopenを呼び出して3番のハンドラを受け取ったら、どうなると思いますか? メインのスレッドも、サブのスレッドも、どっちも「3番のハンドラ」を受け取ります。 メインとサブで異なるファイルをオープンしているのに、ライブラリがグローバル変数で「次の空きは3番」なんて情報を持っていた所為で、両方とも「3番」を受け取ってしまったのです。 もちろん、実際のfopenは「マルチスレッドであっても一意」になっているヒープ領域を用いて「スレッドが切り替わっても大丈夫」な作り(つまり、スレッドセーフ)になっているので、こういう事は起きません。 ライブラリ内にグローバル変数を作ると「マルチスレッド禁止」になっちゃうので、スレッドセーフにするなら、グローバル変数は作ってはいけません。ライブラリ内の変数は、必ず「外にスコープを持たないstatic変数」にしないといけません。