在共享库中初始化全局数据的最佳方法是什么?
what is the best way to initialize my global data in shared library?
我有一个单独的类来完成所有需要的初始化。目前我已经声明了这个类类型的全局对象,它在库加载时被实例化。我也见过其他方法,比如声明
BOOL APIENTRY DllMain
共享库的入口点,并对附加的进程进行实际的初始化。
这与让隐式全局初始化它的工作不同吗?哪一种方式更好?
这是在c++ DLL启动时发生的事情:
- 系统调用DLL的入口点,由编译器生成
- 入口点调用DllMainCRTStartup(名称可能不同),它初始化C/c++运行时并实例化所有全局对象。
- DllMainCRTStartup然后调用用户自定义的DllMain。
我个人更喜欢dlmain,因为这样我可以显式地控制初始化的顺序。当您在不同的编译单元中使用全局对象时,它们将按随机顺序初始化,这可能会在截止日期前10分钟带来一些意想不到的惊喜。
DllMain还允许您执行每个线程的初始化,这是全局对象无法实现的。但是,它不能移植到其他平台。
注:在DllMain中不需要互斥锁,因为对它的所有调用都已经在进程全局临界区下序列化了。也就是说,它保证两个线程不会出于任何目的同时进入它。这也是为什么你不应该与其他线程通信,从这个函数加载其他库等的原因;
在DllMain中不应该做的事情:
- 调用LoadLibrary或LoadLibraryEx(直接或间接)。这可能导致死锁或崩溃。与其他线程同步。这可能导致死锁。获取一个同步对象,该对象由等待获取加载器锁的代码所拥有。这可能导致死锁。通过使用CoInitializeEx初始化COM线程。在某些条件下,这个函数可以调用LoadLibraryEx。
- 调用注册表函数。这些函数在Advapi32.dll中实现。如果Advapi32.dll没有在DLL之前初始化,DLL可以访问未初始化的内存并导致进程崩溃。
- CreateProces打电话。创建进程可以加载另一个DLL。
- ExitThread打电话。在DLL分离期间退出线程可能会导致加载器锁定再次被获取,从而导致死锁或崩溃。
- CreateThread打电话。如果你不与其他线程同步,创建一个线程可以工作,但它是有风险的。
- 创建命名管道或其他命名对象(仅限Windows 2000)。在Windows 2000中,命名对象由终端服务DLL提供。如果这个DLL没有初始化,调用DLL可能会导致进程崩溃。
- 使用动态C运行时(CRT)的内存管理功能。如果没有初始化CRT DLL,调用这些函数会导致进程崩溃。
- 调用User32.dll或Gdi32.dll中的函数。
- 使用托管代码
需要一个静态布尔初始化变量和一个互斥锁。静态初始化"initialized"为0。在你的dlmain()中,调用CreateMutex()。使用bInitialOwner=0和lpName的唯一名称,该名称对您的应用程序来说是唯一的。然后使用WaitForSingleObject()等待互斥对象。检查initialized是否为非零。如果没有,进行初始化,然后将initialized设置为1。如果initialized非零,什么都不做。最后,使用ReleaseMutex()释放互斥锁,并使用CloseHandle()关闭它。
下面是一些伪代码,省略了错误和异常处理:initialized = 0;
DllMain()
{
mutex = CreateMutex(..., 0, "some-unique-name");
result = WaitForSingleObject(handle, ...);
if (result == WAIT_OBJECT_0) {
if (!initialized) {
// initialization goes here
initialized = 1;
}
}
ReleaseMutex(mutex);
CloseHandle(mutex);
}
嗨,我建议你选择单例类,你只能创建一个类的单个对象并使用它。单例类可以用私有构造函数创建。现在假设我们的class A
是一个单例类,它的对象可以在我们想要初始化的每个类的构造函数中使用。请给我们一些示例代码,以便其他可能帮助你更好。
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 在C++中向零方向近似的最佳方法
- 使用不同的CRT将新的C++代码与旧的(二进制)组件隔离开来的最佳方法是什么
- 检测win32服务创建和删除的最佳方法
- 在C++中样板"冷/never_inline"错误处理技术的最佳方法是什么?
- 在 c++ 中对类中的 c 字符串动态数组进行排序的最佳方法是什么?
- 将线程中的数据存储到全局容器的最佳方法?
- 将一系列整数放入类的最佳方法是什么?
- 在派生类中使用基类的私有成员变量的最佳方法
- 在 C++ 中将非指定类型作为参数传递的最佳方法?
- Qt - QVector 和模型视图 - 从列表视图获取自定义类的最佳方法是什么?
- 使用 Git 处理 C++ Visual Studio 2019 解决方案的外部依赖项源代码管理的最佳方法是什么?
- 比较两个节点坐标的最佳方法是什么?
- 在nodejs中使用本机代码的最佳方法是什么?
- 将 pybind11 绑定标记为已弃用的最佳方法
- C++:将向量传递到构造函数以创建成员变量的最佳方法?
- C++中变量混叠的最佳方法
- 读取大文件(>2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是什么?