我正在编写一些代码来执行与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 :(得分:1)
此代码在x86和amd64上完全安全。
在最坏的情况下,GetProcAddress
被多次调用。
在其他架构上,可能存在部分写入被中断的问题。为了避免这种情况,你可以使用原子(InterlockedComparExchange
...),但这在这里是多余的。
答案 1 :(得分:0)
一个简单的锁应该这样做
你应该只在proc==NULL
时使用锁,所以一段时间后它就永远不会被拿走。所以争论不是问题
您可以在持有锁定的情况下致电GetProcAddress
,或不使用锁定。{/ p>
选项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();
}