我不确定如何在DLL和共享对象中管理静态全局内存。我不知道每个人是否在不同的平台上以相同或不同的方式处理它。
考虑你有一个类库,其中一个类是互斥类,库中的其他类将使用该互斥。在库中分配互斥锁的最佳或最安全的方法是什么?我可以看到几个选项:
在类中将互斥锁设为私有。这个我看不到工作,因为互斥生命只会在对象的生命周期内有效。也许使对象成为单例,并在加载库时使用dllattach或属性((构造函数))初始化它会起作用,我不确定。
在库的静态全局空间中分配类外部的互斥锁。我认为这将是最好的选择,但是在加载DLL时会发生什么?如果我在库中创建一个静态和全局的对象,它何时被分配,程序中的哪个被分配?如果在运行时加载库而不是程序启动时会发生什么?
非常感谢有关此事的任何信息!
答案 0 :(得分:2)
在共享映像中管理内存的方式取决于特定平台,而DLL则特定于Microsoft Windows。
通常,您应该始终避免使用全局/共享静态变量,因为它们可能会引入严重的问题或难以识别或解决的错误。即使是单例类也可能导致several issues in C++,特别是在库或多线程应用程序中。 (通常,即使在更高级别的语言中也使用单身are not considered good。)
为了防止互斥竞争条件,最好的选择是使用RAII technique与shared_ptr
smart pointer一起使用的{em>范围锁类,它自动化内存分配和解除分配。
以下代码说明了使用Windows API和上述技术(以及Pimpl idiom)实现Mutex
:
// Mutex.h
#pragma once
#include <memory>
class Mutex
{
public:
typedef unsigned long milliseconds;
Mutex();
~Mutex();
void Lock();
void Unlock();
bool TryLock();
bool TimedLock(milliseconds ms);
private:
struct private_data;
std::shared_ptr<private_data> data;
// Actual data is hold in private_data struct which is non-accessible.
// We only hold a "copyable handle" to it through the shared_ptr, which
// prevents copying this "actual data" object by, say, assignment operators.
// So, private_data's destructor automatically gets called only when the last
// Mutex object leaves its scope.
};
// Mutex.cpp
#include "Mutex.h"
#include <windows.h>
struct Mutex::private_data
{
HANDLE hMutex;
private_data()
{
hMutex = CreateMutex(NULL, FALSE, NULL);
}
~private_data()
{
// Unlock(); ?? :/
CloseHandle(hMutex);
}
};
Mutex::Mutex()
: data (new private_data())
{ }
Mutex::~Mutex()
{ }
void Mutex::Lock()
{
DWORD ret = WaitForSingleObject(data->hMutex, INFINITE);
ASSERT(ret == WAIT_OBJECT_0);
}
void Mutex::Unlock()
{
ReleaseMutex(data->hMutex);
}
bool Mutex::TryLock()
{
DWORD ret = WaitForSingleObject(data->hMutex, 0);
ASSERT(ret != WAIT_ABANDONED);
ASSERT(ret != WAIT_FAILED);
return ret != WAIT_TIMEOUT;
}
bool Mutex::TimedLock(milliseconds ms)
{
DWORD ret = WaitForSingleObject(data->hMutex, static_cast<DWORD>(ms));
ASSERT(ret != WAIT_ABANDONED);
ASSERT(ret != WAIT_FAILED);
return ret != WAIT_TIMEOUT;
}
// ScopedLock.h
#pragma once
#include "Mutex.h"
class ScopedLock
{
private:
Mutex& m_mutex;
ScopedLock(ScopedLock const&); // disable copy constructor
ScopedLock& operator= (ScopedLock const&); // disable assignment operator
public:
ScopedLock(Mutex& mutex)
: m_mutex(mutex)
{ m_mutex.Lock(); }
~ScopedLock()
{ m_mutex.Unlock(); }
};
样本用法:
Mutex m1;
MyClass1 o1;
MyClass2 o2;
...
{
ScopedLock lock(m1);
// thread-safe operations
o1.Decrease();
o2.Increase();
} // lock is released automatically here upon leaving scope
// non-thread-safe operations
o1.Decrease();
o2.Increase();
虽然上面的代码将为您提供基本的想法,但更好的选择是使用高质量的C ++库,如boost,其中mutex
, scoped_lock
和许多其他类已经可用。 (幸运的是,C ++ 11完全覆盖了同步类,使您无需使用boost库。)
更新:
我建议你搜索有关C ++自动垃圾收集以及RAII技术的主题。