【发布时间】:2015-11-09 04:09:39
【问题描述】:
我想在我们的开源库中使用 C++11 关键字 thread_local,它可以在许多平台(Windows、Linux、Mac OS 等)上动态或静态链接,在静态变量。这个变量是一个类类型,基本上只是封装了一个 std::stringstream 变量并对其进行初始化以适应我们的字符串流格式要求。出于性能原因,我们希望静态可用(有关更多详细信息,请参阅我以前的question),如果每个线程都这样做是可以的。
全局变量应该在静态模板类方法中使用,这些方法必须在头文件中实现。但这意味着,如果我理解正确,该库的用户可能会在其可执行文件的代码中包含此标头,这会将模板化方法编译到可执行文件中。然后,这些方法将从可执行文件的线程中访问提到的全局变量。我需要如何声明/定义静态变量才能使其工作,即我需要导出变量或类类型还是将其声明为“静态 thread_local X”就足够了?这是我目前的声明:
// SharedStringstream.h
#include <sstream>
// Export stands for _declspec(dllimport) or (dllexport) respectively
class EXPORT SharedStringstream
{
public:
SharedStringstream();
static thread_local SharedStringstream s_sharedStreamInstance;
std::stringstream d_sharedStream;
};
以及定义:
// SharedStringstream.cpp
#include "SharedStringStream.h"
SharedStringstream SharedStringstream::s_sharedStreamInstance();
SharedStringstream::SharedStringstream()
{
d_sharedStream.imbue(std::locale("C"));
d_sharedStream << std::skipws;
d_sharedStream >> std::skipws;
}
如果没有导出,我会收到链接器错误,因此我会在 Visual Studio 2015 中收到以下错误:
错误 C2492 'public: static SharedStringstream SharedStringstream::s_sharedStreamInstance': 具有线程存储持续时间的数据可能没有 dll 接口
here 提供了更多信息,该信息基本上表明可能无法导出 thread_local 变量。为此,我必须将它从类中移出到我的命名空间中,这是唯一的方法吗?
此外:
"Thread Local Storage" 上的 MSDN 页面关于 thread_local 和 DLL 的内容如下:
使用 thread 属性可能会干扰 DLL 导入的延迟加载。
对于我们的库所包含的某些插件,我们确实在内部使用延迟加载 DLL,但不会对变量进行任何调用。但是,我假设用户可以延迟加载库,尽管我们不正式支持这一点。假设我们不支持库的延迟加载并且不在内部从任何延迟加载的 dll 中调用变量,我们是否能够确定这在任何情况下都不会成为问题?
在我的问题中有没有我没有考虑过的问题?
【问题讨论】:
-
当你说'对于一个静态变量'时,你真的是指作为一个静态变量吗?如果不是,那是什么?
-
@EJP 我改写了,更好吗?我不知道该怎么说更好。如果还是看不懂,请提出建议。
-
您找到解决问题的方法了吗?我问是因为我有同样的问题......
-
感觉有点像xkcd漫画:上古智慧xkcd.com/979
-
@mattmilten 是的,只是我总是回复 :D 对于它的价值,我还没有遇到我们的 atm 设置的任何问题,也没有人抱怨。