1

Say we have a class Foo defined as follows:

// foo.hpp
class Foo;

using FooCallback = std::function<void(std::shared_ptr<Foo> ins)>;

class Foo : public std::enable_shared_from_this<Foo>{
public:
  Foo(int b, const FooCallback& callback):m_bar(b),
                                          m_callback(callback){}

  int
  getBar();

  void
  doSth();

private:
  int m_bar;
  const FooCallback& m_callback;
};

Why will the following code cause segment fault?

// foo.cpp
#include "foo.hpp"

int
Foo::getBar(){
  return m_bar;
}

void
Foo::doSth(){
  std::cout << "Start ... " << std::endl;
  this->m_callback(shared_from_this());
  std::cout << "End ... " << std::endl;
}

int main()
{
  auto f = std::make_shared<Foo>(100,
        [](std::shared_ptr<Foo> ins){
          std::cout << "bar: " << ins->getBar() << std::endl;
        });
  f->doSth();
  return 0;
}

The output is:

Start ...

segmentation fault

To my understanding, this is what is going on:

  1. In main(), f is a shared_ptr pointing to an instance of Foo, say it's ins.
  2. When f->doSth() is called, ins.doSth() is actually called.
  3. In ins.doSth, this is a pointer to ins. And shared_from_this() is a shared_ptr to ins.

So why is step 3 causing the segment fault?

Community
  • 1
  • 1

1 Answers1

3

This has nothing to do with shared_from_this. If you look in the debugger, it shows that this segfaults at the location where the std::function's internal pointer points to.

And this happens because m_callback is a reference, and the function object that it refers doesn't exist anymore when you call doSth (because it was a temporary object).

To fix this you can save m_callback by value:

const FooCallback m_callback;

Or even better, since the lambda doesn't capture anything, you could make m_callback a plain function reference (or pointer):

using FooCallback = void(std::shared_ptr<Foo> ins);

…

  FooCallback& m_callback;

…

auto f = std::make_shared<Foo>(100,
        *[](std::shared_ptr<Foo> ins){
          std::cout << "bar: " << ins->getBar() << std::endl;
        });
Emil Laine
  • 41,598
  • 9
  • 101
  • 157
  • Thank you very much. I found these concepts really confusing. I know maybe I shouldn't ask this, but would please recommend me some readings on learning modern c++? – stupidlearner Mar 07 '17 at 23:22
  • 1
    I haven't read any C++ books so I can't personally recommend anything but check [this](http://stackoverflow.com/q/388242/3425536) out. – Emil Laine Mar 07 '17 at 23:22