c++ - 动态加载库中的 thread_local 静态变量——它们是什么时候创建的?
问题描述
cppreferencethread_local
在变量上声明了以下内容
对象的存储在线程开始时分配,在线程结束时释放。每个线程都有自己的对象实例。只有声明为 thread_local 的对象具有此存储持续时间。
我想使用在运行时通过/thread_local static
加载的共享库中声明的成员变量。由于完全有可能在加载该库的时间点已经有相当多的线程在运行,其中一些线程稍后将访问该变量,我想知道如果在线程开始时分配存储空间,这是如何工作的?如果在创建线程的时间点程序中不存在该变量,这显然不能像那里解释的那样工作。此外,如果运行例如 100 个线程的进程会为每个线程创建该线程局部变量的实例,而其中只有少数线程实际访问该变量,这似乎是一种资源浪费。dlopen
LoadLibrary
那么,这里的文档是不正确的,还是我在这里尝试的可能会导致未定义的行为?如果文档完全不正确,我在哪里可以找到关于现实中可以预期的可靠描述?如果它是定义的实现,我对 clang 如何在 macOS 和 Windows 上处理它特别感兴趣。
解决方案
cppreference 所说的是意译。标准中的实际内容是
thread_local
使用关键字声明的所有变量都有线程存储持续时间。这些实体的存储将持续到创建它们的线程的持续时间。每个线程都有一个不同的对象或引用,使用声明的名称是指与当前线程关联的实体。
那里没有关于何时分配存储的确切信息,只是它在线程期间持续存在。这意味着它可以在创建线程时分配,或者在第一次使用变量时分配,或者可能是两者的组合。
分配存储时,可能不会构造变量(我假设这就是您说“创建实例”时的意思)。这取决于变量的定义位置和方式。但是,如果它被构造,它不会被销毁,直到线程结束。
支持通过dlopen
或者LoadLibrary
是编译器/平台扩展来动态加载库,而不是语言的一部分。如何与之交互thread_local
也将是特定于平台的。
推荐阅读
- git - 如何从原点完全删除分支,以使 repo 大小也减小
- vue.js - Vuepress - 组件定制
- regex - 用正则表达式匹配浮点数
- delphi - Delphi 10.4 事件视图在调试期间未更新
- javascript - 用于移动设备的 window.print
- gitlab - 如何添加带有动态分支的 gitlab 徽章?
- android - getEnabledAccessibilityServiceList 返回错误的结果
- react-native - 为什么不能在使用 Hooks 的 React Native 中清除 TextInput 中的值?
- google-cloud-platform - 在谷歌云上注册失败,出现错误“您的请求失败。[OR-CCSEH-23]
- .net-core - 如何在 dotnet 中获取所有国家/地区名称的翻译列表