我试图在C ++中实现一个非常基本的Thread Local Singleton类 - 它是一个其他类继承的模板类。问题是它几乎总是有效,但不时(例如,15次运行),它将失败并出现以下错误:
*检测到glibc * ./myExe:free():下一个大小无效(快):0x00002b61a40008c0 ***
请原谅下面相当人为的例子,但这有助于证明这个问题。
#include <thread>
#include <atomic>
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
template<class T>
class ThreadLocalSingleton
{
public:
/// Return a reference to an instance of the object
static T& instance();
typedef unique_ptr<T> UPtr;
protected:
ThreadLocalSingleton() {}
ThreadLocalSingleton(ThreadLocalSingleton const&);
void operator=(ThreadLocalSingleton const&);
};
template<class T>
T& ThreadLocalSingleton<T>::instance()
{
thread_local T m_instance;
return m_instance;
}
// Create two atomic variables to keep track of the number of times the
// TLS class is created and accessed.
atomic<size_t> creationCount(0);
atomic<size_t> accessCount(0);
// Very simple class which derives from TLS
class MyClass : public ThreadLocalSingleton<MyClass>
{
friend class ThreadLocalSingleton<MyClass>;
public:
MyClass()
{
++creationCount;
}
string getType() const
{
++accessCount;
return "MyClass";
}
};
int main(int,char**)
{
vector<thread> threads;
vector<string> results;
threads.emplace_back([&]() { results.emplace_back(MyClass::instance().getType()); MyClass::instance().getType(); });
threads.emplace_back([&]() { results.emplace_back(MyClass::instance().getType()); MyClass::instance().getType(); });
threads.emplace_back([&]() { results.emplace_back(MyClass::instance().getType()); MyClass::instance().getType(); });
threads.emplace_back([&]() { results.emplace_back(MyClass::instance().getType()); MyClass::instance().getType(); });
for (auto& t : threads)
{
t.join();
}
// Expecting 4 creations and 8 accesses.
cout << "CreationCount: " << creationCount << " AccessCount: " << accessCount << endl;
}
我可以使用build命令在coliru上复制它: g ++ -std = c ++ 11 -O2 -Wall -pedantic -pthread main.cpp&amp;&amp; ./a.out
非常感谢!
答案 0 :(得分:1)
感谢molbdnilo和Damon,他们很快指出了明显的 - vector :: \ templace_back不是线程安全的,所以不能保证这段代码是否真的有效。我用以下内容替换了main()函数,这似乎更可靠。
int main(int,char**)
{
vector<thread> threads;
vector<string> results;
auto addToResult = [&results](const string& val)
{
static mutex m_mutex;
unique_lock<mutex> lock(m_mutex);
results.emplace_back(val);
};
threads.emplace_back([&addToResult]() { addToResult(MyClass::instance().getType()); MyClass::instance().getType(); });
threads.emplace_back([&addToResult]() { addToResult(MyClass::instance().getType()); MyClass::instance().getType(); });
threads.emplace_back([&addToResult]() { addToResult(MyClass::instance().getType()); MyClass::instance().getType(); });
threads.emplace_back([&addToResult]() { addToResult(MyClass::instance().getType()); MyClass::instance().getType(); });
for (auto& t : threads)
{
t.join();
}
// Expecting 4 creations and 8 accesses.
cout << "CreationCount: " << creationCount << " AccessCount: " << accessCount << endl;
}
谢谢!