为什么使用 thread_local 变量会导致段错误?
Why does using thread_local variable cause a segfault?
我在 class A
中创建了一个堆上数组,然后创建了一个 thread_local A
对象。通过 A
访问堆上存储会导致段错误,为什么?
#include <chrono>
#include <iostream>
#include <memory>
#include <thread>
#include <vector>
class A {
public:
A() {
std::cout << ">>>> constructor >>>>" << std::endl;
a = new int[10];
}
~A() {
std::cout << ">>>> destructor >>>>" << std::endl;
delete[] a;
}
void set(int x) { a[0] = x; }
int get() const { return a[0]; }
private:
int* a;
};
int main() {
std::thread t1;
{
thread_local A t;
t1 = std::thread([]() {
t.set(1);
std::cout << t.get() << std::endl;
});
}
t1.join();
std::cout << ">>>> main >>>>" << std::endl;
}
结果:
>>>> constructor >>>>
Segmentation fault (core dumped)
t
仅在 when your code passes through it in main
中初始化。由于 t1
是一个单独的线程,它的 t
是变量的一个单独实例,但它没有被初始化,因为 t1
中的代码从不执行声明 t
的行。
如果我们将 t
更改为全局 then the rules are different 并且每个线程自动初始化它自己的 t
副本并且您的代码正确执行:
thread_local A t;
int main() {
std::thread t1;
{
t1 = std::thread([]() {
t.set(1);
std::cout << t.get() << std::endl;
});
}
t1.join();
std::cout << ">>>> main >>>>" << std::endl;
}
与您的问题无关,但您应该确保您的代码遵守 rule of three 并删除或实现复制构造函数和赋值运算符,否则此代码将具有未定义的行为,因为两个对象都将尝试删除 a
:
A a1;
A a2 = a1;
我在 class A
中创建了一个堆上数组,然后创建了一个 thread_local A
对象。通过 A
访问堆上存储会导致段错误,为什么?
#include <chrono>
#include <iostream>
#include <memory>
#include <thread>
#include <vector>
class A {
public:
A() {
std::cout << ">>>> constructor >>>>" << std::endl;
a = new int[10];
}
~A() {
std::cout << ">>>> destructor >>>>" << std::endl;
delete[] a;
}
void set(int x) { a[0] = x; }
int get() const { return a[0]; }
private:
int* a;
};
int main() {
std::thread t1;
{
thread_local A t;
t1 = std::thread([]() {
t.set(1);
std::cout << t.get() << std::endl;
});
}
t1.join();
std::cout << ">>>> main >>>>" << std::endl;
}
结果:
>>>> constructor >>>>
Segmentation fault (core dumped)
t
仅在 when your code passes through it in main
中初始化。由于 t1
是一个单独的线程,它的 t
是变量的一个单独实例,但它没有被初始化,因为 t1
中的代码从不执行声明 t
的行。
如果我们将 t
更改为全局 then the rules are different 并且每个线程自动初始化它自己的 t
副本并且您的代码正确执行:
thread_local A t;
int main() {
std::thread t1;
{
t1 = std::thread([]() {
t.set(1);
std::cout << t.get() << std::endl;
});
}
t1.join();
std::cout << ">>>> main >>>>" << std::endl;
}
与您的问题无关,但您应该确保您的代码遵守 rule of three 并删除或实现复制构造函数和赋值运算符,否则此代码将具有未定义的行为,因为两个对象都将尝试删除 a
:
A a1;
A a2 = a1;