Home > Blockchain >  Why does using thread_local variable cause a segfault?
Why does using thread_local variable cause a segfault?

Time:04-12

I create an on-heap array in class A and then create a thread_local A object. Accessing on-heap storage via A causes a segfault, why?

#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;
}

Result:

>>>> constructor >>>>
Segmentation fault (core dumped)

CodePudding user response:

t is only initialised in when your code passes through it in main. As t1 is a separate thread its t is a separate instance of the variable but it is not initialised as the code in t1 never executes the line where t is declared.

If we change t to a global then the rules are different and each thread automatically initialises it's own copy of t and your code executes correctly:

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;
}

Unrelated to your problem but you should make sure that your code obeys the rule of three and either delete or implement the copy constructor and assignment operator otherwise this code will have undefined behaviour as both objects will try to delete a:

A a1;
A a2 = a1;
  • Related