是否有可能多个动态链接库(DLL)从静态库(LIB)共享线程本地存储

Goo*_*ose 6 c++ dll multithreading static-libraries thread-local-storage

我有一个由许多DLL文件组成的游戏.其中一些DLL链接到相同的静态库(LIB).

所以像这样:

Game.exe -> Root.dll -> Child.dll
               |            |
               |            '-> Common.lib (contains __declspec(thread))
               |
               '-> Common.lib (contains __declspec(thread))
Run Code Online (Sandbox Code Playgroud)

Root.dll加载静态链接Common.lib的Child.dll.Root还静态链接Common.lib.因为Common是静态链接的,所以它会直接编译到加载dll中(例如Root和Child).

Common.lib包含使用线程本地存储(TLS)的变量.

__declspec(thread) static void* s_threadValues[PlatformThreadSlotsMax];
Run Code Online (Sandbox Code Playgroud)

这会导致一些有问题的行为:Root.dll和Child.dll每个都包含一个不同的TLS数据实例(s_threadValues).即使在同一个线程上,如果Root.dll调用Common.lib中定义的函数,如果从Child.dll调用相同的函数,则s_threadValues的值将与其值不同.

由于两个DLL都是从同一个线程访问这个TLS,我希望共享TLS,但事实并非如此.

现在,如果我将Common.lib更改为动态链接(例如Common.dll),则不会出现此问题:对于Root.dll和Child.dll,s_threadValues是相同的.

这是预期的行为吗?无论如何在动态库之间共享静态库中定义的TLS共享使用它吗?

Han*_*ant 6

这完全正常.每个DLL都有自己的库代码和数据副本.它自己的线程本地状态.

您可以通过假设它按照您预期的方式工作来解释这一点.然后两个DLL可能会意外地在不同的DLL之间共享自己的线程局部变量.显然这将是灾难性的.它无法以这种方式工作,因为没有机制可以跨模块共享TLS实例.槽索引有意保持模块专用,没有机制来获取__declspec(线程)变量的槽索引.显式调用TlsAlloc()并共享索引将是一种解决方法.不要去那里.

  • 结论:将“通用”库保留为自己的独立 DLL 是正确的方法。轻松入睡。 (2认同)