0

I have a class which runs a background task when it is constructed (see the constructor). This task is then stopped and the thread is joined in the destructor when the object is destroyed:

// Foo.hpp -------------------------------
#include <boost/thread.hpp>
#include <boost/date_time/posix_time.hpp>

class Foo {
  boost::thread theThread;

  Foo();
  ~Foo();
  void bar() const;
}

// Foo.cpp -------------------------------
// This is the background task.
void Foo::bar() const {
  while (true) {
    try {
      // sleep for 1 minute.
      boost:this_thread_sleep(boost::posix_time::minutes(1));

      // do other stuff endlessly
    }

    // boost interrupt was called, stop the main loop.
    catch (const boost::thread_interrupted&)
    {
      break;
    }
}

// Instantiate background task
Foo::Foo()
    : theThread(&Foo::bar, this)
{
    // do other stuff
}

// Stop background task
Foo::~Foo() {
    theThread.interrupt()
    theThread.join();
}

Now this works fine when I have a single instance to the class:

// main.cpp
Foo f;
// do other stuff with f

But when I do this I get a segmentation fault and an aborted message:

// main.cpp
Foo *f;
f = new Foo(); // causes seg fault
delete f;

Why?

  • 1
    Does `boost::thread` attempt to dereference the second parameter in its constructor (in your case, `this`)? If so, then using `this` as an argument in your initialization list doesn't seem to be safe. – PaulMcKenzie May 04 '17 at 15:23
  • Not sure if foo::bar is constructed yet when you give it to the thread – didiz May 04 '17 at 16:39
  • Sorry, but your code does not compile and your destructor is private so you cannot instantiate this class in main.cpp. Are you sure this code reproduces your problem? – J. Calleja May 04 '17 at 21:57

1 Answers1

0

Xcode gives the error:

Attempting to use a deleted function

Foo::Bar is not callable with the syntax above(&Foo::Bar), since it is not a static function. It has a hidden this parameter which causes the signatures not to match.

More on this here: pthread function from a class

Also it is bad practice to use member functions on initializer lists, the behavior is undefined. Quoted here:

Member functions (including virtual member functions) can be called from member initializers, but the behavior is undefined if not all direct bases are initialized at that point.

http://en.cppreference.com/w/cpp/language/initializer_list

The following works:

   void bar(atomic_int*exit) {
    while (*exit) {
        // sleep for 1 minute.
        this_thread::sleep_for(std::chrono::seconds(2));

        // do other stuff endlessly

    }
}

class Foo {
    thread theThread;
    atomic_int _exit;

public:
   // Instantiate background task
    Foo(): _exit(1)
    {
        // do other stuff
        init();
    }
    void init()
    {
        theThread = std::thread (&bar,&_exit);
    }

    // Stop background task
    ~Foo() {
        _exit = 0;
        theThread.join();
    }
};
Community
  • 1
  • 1
didiz
  • 1,069
  • 13
  • 26
  • No std::thread or atomic types in my c++ version, sorry bro, doesn't work. –  May 05 '17 at 16:38
  • Sorry I don't use boost but it does have boost::atomic if you wish to look further. In any case you can't pass the member function this way need to externalize it or make it static. – didiz May 05 '17 at 16:41