2012-03-21 21 views
1

DLLへの明示的なリンクを実行するためのコードを記述しています。このコードは、.libファイルとの暗黙的なリンクの代用としてユーザーに提供されます。現時点では私の計画のコードは次のようになります。このコードに同期を追加する必要はありますか?

void DisableModule(int Module) 
{ 
    typedef void (*DisableModuleProc)(int); 
    static DisableModuleProc proc = NULL; 
    if (proc == NULL) 
     proc = (DisableModuleProc)GetProcAddress(hModule, "DisableModule"); 
    proc(Module); 
} 

は、このフォームの機能がたくさんありますが、私はこの質問の目的のためにエラーチェックを切除しています。

私の問題は、スレッドの安全性に関係しています。この関数は、複数のスレッドから同時に呼び出される可能性があります。明らかに、静的変数_DisableModuleにはレースがあります。私の信念は、_DisableModuleが機械語の境界(ターゲットに応じて32または64ビット境界のいずれか)に整列するため、引き裂きが発生しないこと、そしてレースが良性であることです。 GetProcAddressが必要以上に多く呼び出される可能性はありますが、それがプログラムの正確性に影響するとは思いません。

私の分析は正しいですか?

+0

呼び出される関数(_DisableModule)自体がスレッドセーフですか?また、アンダースコアと大文字で始まる識別子は予約されています。 – zvrba

+0

@zvrbaはい、インポートされた関数はスレッドセーフです。予約済み識別子に関するアドバイスをありがとうございました。私はCに堪能ではない。 –

+0

プロセッサの種類によって異なりますが、x86またはx64の場合はうまく動作します。 ARMについてはあまり確かではありませんが、弱いメモリモデルを持っています。スレッドを使用しているときは、常に「申し訳ありません」よりも安全です。 –

答えて

2

このコードは、x86とAMD64に完全に安全です。 最悪の場合GetProcAddressが何回か呼び出されます。

他のアーキテクチャでは、部分的な書き込みが中断される問題があります。これを回避するために、アトミック(InterlockedComparExchange ...)を使用できますが、ここでは余計です。

+0

あなたは、いくつかのアーキテクチャでは、機械語のサイズ調整された書き込みは、読み取りに関して原子的ではないと言っていますか? –

+1

Aehm、ポインタがワードサイズではないアーキテクチャ(32ビット(far)ポインタを持つ16ビットアーチなど)、またはアラインされていないアドレスでの書き込みが許可されているが、キャッシュライン境界ではアトミックではないかもしれません... 。しかし、あなたはそれらの窓を走らせることはできません...。 – Christopher

0

シンプルなロックが必要です。
proc==NULLの場合にのみロックを取る必要がありますので、しばらくしてからかかりません。したがって、競合は問題ではありません。
GetProcAddressには、ロックを保持したまま、またはロックなしで呼び出すことができます。

オプション1:

if (proc == NULL) { 
    lock(); 
    proc = (DisableModuleProc)GetProcAddress(hModule, "DisableModule"); 
    unlock(); 
} 

オプション2:

if (proc == NULL) { 
    DisableModuleProc tmp = (DisableModuleProc)GetProcAddress(hModule, "DisableModule"); 
    lock(); 
    if (proc == NULL) { 
     proc = tmp; 
    } else { 
     // Any free needed? 
    } 
    unlock(); 
} 
+0

ありがとうございますが、私はロックの必要性を避けようとしています。 –

+0

'GetProcAddress'がスレッドセーフで、常に同じものを返したら、あなたは本当に上手です。しかし、ロックは私が提案した方法とほとんど無関係です。 – ugoren

+0

スレッドセーフです。しかし、そうでなければ、あなたの選択肢2は失敗するでしょう。 –

関連する問題