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:
In main(), f is a shared_ptr pointing to an instance of Foo, say it's ins.
When f->doSth() is called, ins.doSth() is actually called.
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?
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;
});
Related
I am having the below code :
std::vector<std::function<void()>> functors;
class Bar
{
public :
Bar(const int x, const int y):d_x(x),d_y(y){}
~Bar(){
cout << "Destructing Bar" << endl;
}
void addToQueue()
{
const auto job = [=](){
cout << "x:" << d_x << " y: " << d_y;
};
functors.push_back(job);
}
private :
int d_x,d_y;
};
void example()
{
cout << "Hello World" << endl;
{
shared_ptr<Bar> barPtr = make_shared<Bar>(5,10);
barPtr->addToQueue();
}
cout << "Out of scope. Sleeping" << endl;
usleep(1000);
functors[0]();
}
The output is as expected :
Hello World
Destructing Bar
Out of scope. Sleeping
x:5 y: 10
I am now capturing by value, which is why I assume when the Bar object gets destroyed, I can still access its member variables. If the above is right, I am expecting the below change to give me UB:
const auto job = [&](){
However, I still see the same result. Why is that? Have i understood something wrong?
EDIT Further on the above, what I want to understand from this example - is how can I have access to a class member variables in a lambda function even if object has been destroyed? I am trying to avoid UB and thought that passing by value is the way to go, but can't prove that the opposite isn't working.
This kind of confusion iss probably one of the reasons why C++20 deprecated the implicit capture of this with [=]. You can still capture [this], in which case you have the usual lifetime issues with an unmanaged pointer. You can capture [*this] (since C+=17), which will capture a copy of *this so you don't have lifetime issues.
You could also use std::enable_shared_from_this since you're using a std::shared_ptr in example, but that's a bit more complicated. Still, it would avoid both the copy and the UB when the lifetime issues.
In these examples you are capturing this and not any of the fields.
When capturing this, by design, it is never captured by copying the object or the fields.
The best way to capture a field by value is:
[field = field] () { }
Both versions of your code have undefined behaviour. barPtr is the only owner of the shared_ptr so your object is destructed at the end of the scope containing barPtr. Executing the lambda which has captured this from the object in barPtr has undefined behaviour.
The usual way to prevent this is for the lambda to capture a shared_pointer from shared_from_this to keep the object alive. E.g:
#include <vector>
#include <functional>
#include <iostream>
#include <memory>
std::vector<std::function<void()>> functors;
class Bar : public std::enable_shared_from_this<Bar>
{
public :
Bar(const int x, const int y):d_x(x),d_y(y){}
~Bar(){
std::cout << "Destructing Bar\n";
}
void addToQueue()
{
auto self = shared_from_this();
const auto job = [this, self](){
std::cout << "x:" << d_x << " y: " << d_y << "\n";
};
functors.push_back(job);
}
private :
int d_x,d_y;
};
int main()
{
std::cout << "Hello World\n";
{
std::shared_ptr<Bar> barPtr = std::make_shared<Bar>(5,10);
barPtr->addToQueue();
}
std::cout << "Out of scope\n";
functors[0]();
}
By capturing self the shared_ptr will now survive for at least as long as the lambda does.
I have a problem with the code that uses function pointer that takes shared_ptr argument.
Here is a sample code.
header.h
#include <functional>
#include <iostream>
template <class T> class FuncWrapper{
private:
void (*original_function)(T a);
public:
void setFunction(void *func);
void execFunction(T a, void *data);
};
template <class T> void FuncWrapper<T>::setFunction(void *func){
original_function = (void (*)(T))func;
}
template <class T> void FuncWrapper<T>::execFunction(T a, void *data){
FuncWrapper<T>* wrapper = (FuncWrapper<T>*)data;
std::cout << "inside wrapper " << *(a.get()) << std::endl;
wrapper->original_function(a);
}
main.cpp
#include <iostream>
#include <memory>
#include "header.h"
class ClassA{
public:
ClassA(std::shared_ptr<int> a){
FuncWrapper<std::shared_ptr<int>> *fw;
fw = new FuncWrapper<std::shared_ptr<int>>;
fw->setFunction((void*)&ClassA::print_int);
std::function<void(std::shared_ptr<int>)> g = std::bind(&FuncWrapper<std::shared_ptr<int>>::execFunction, fw, std::placeholders::_1, fw);
g(a);
delete fw;
}
private:
void print_int(std::shared_ptr<int> x) {
std::cout << "printing int" << std::endl;
std::cout << "given int " << *(x.get()) << std::endl;
}
};
int main(int argc, char * argv[]){
std::shared_ptr<int> x = std::make_shared<int>(10);
std::cout << "inside main " << *(x.get()) << std::endl;
ClassA *temp;
temp = new ClassA(x);
delete temp;
return 0;
}
Result
inside main 10
inside wrapper 10
printing int
Segmentation fault (core dumped)
I cannot figure out why it causes segmentation fault.
Changing std::shared_ptr<int> to int works just fine.
Therefore I assume that it has to do with owenership of shared_ptr, but I'm not familiar with smart pointers and I'm completely at loss.
I want to know
why it does not work
how to make it work
Limitations are
w/o changing print_int function itself
execute function within FuncWrapper<T>::execFunction
FuncWrapper<T>::execFunction has to be static
Otherwise, it is free to change. (inside ClassA constructor, inside main execFunction etc.)
The problem is not the shared_ptr, but mismatch between pointers to a function and a member function.
Your function wrapper expects a pointer to a function (void (*)(std::shared_ptr<int>)), but you provide a pointer to a member function (void (ClassA::*)(std::shared_ptr<int>)), which is different. An implicit leading argument of pointer to this is added to it.
This is how it really looks like:
// pointer to member function
void (*)(ClassA *ptr, std::shared_ptr<int>)
Your shared_ptr goes to the first argument and fortunately the application segfaults.
One of the solutions is to make the function print_int static.
class ClassA{
public:
ClassA(std::shared_ptr<int> a){
FuncWrapper<std::shared_ptr<int>> *fw;
fw = new FuncWrapper<std::shared_ptr<int>>;
fw->setFunction((void*)&ClassA::print_int);
std::function<void(std::shared_ptr<int>)> g = std::bind(&FuncWrapper<std::shared_ptr<int>>::execFunction, fw, std::placeholders::_1, fw);
g(a);
delete fw;
}
private:
static void print_int(std::shared_ptr<int> x) {
std::cout << "printing int" << std::endl;
std::cout << "given int " << *(x.get()) << std::endl;
}
};
But there seems to be another problem in your code. Function pointers should not be converted to object pointers (which void * is). Maybe change your setFunction this way:
void setFunction(void (*func)(T)) {
original_function = func;
}
More on that here
Can someone explain why is the destructor of class bar being called in the line where the object of the same type is being initialized?
#include <memory>
#include <iostream>
using namespace std;
class bar
{
public:
bar() {}
~bar() { std::cout << "destructor called " << std::endl; }
};
class foo
{
public:
foo(std::shared_ptr<bar> barP) {}
};
int main() {
std::shared_ptr<foo> f;
std::cout << "before init " << std::endl;
f = std::shared_ptr<foo>(new foo(std::shared_ptr<bar>(new bar())));
std::cout << "after init" << std::endl;
}
Output:
before init
destructor called
after init
This statement:
f = std::shared_ptr<foo>(new foo(std::shared_ptr<bar>(new bar())));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
constructs a temporary shared_ptr which goes out of scope at the end of the statement. At that point, the shared_ptr goes away, taking bar with it (since no copies of the shared_ptr remain alive).
But if you change foo to read like this:
class foo
{
public:
foo(std::shared_ptr<bar> barP) { m_bar = barP; }
std::shared_ptr<bar> m_bar;
};
Then the output you get is probably what you were expecting, because foo maintains a copy of the shared_ptr until it (foo) goes out of scope and that copy keeps bar alive:
before init
after init
destructor called
Live demo
It's because the bar instance only lives as long as the duration of the foo constructor. So it gets constructed, passed into the shared_ptr, which is then into the foo constructor. As soon as that constructor is done (even if on the same line) the expression itself is done, and so the shared_ptr is done, and destructs.
At the end of main right before the cout, you still have a shared_ptr to foo in f, but the unnamed shared_ptr to your bar object has already gone "out of scope".
First of all, you should not instantiate shared_ptr in this way, use make_shared to instantiate shared_ptr. Please check the modified code -
#include <memory>
#include <iostream>
using namespace std;
class bar
{
public:
bar() {}
~bar() { std::cout << "destructor called " << std::endl; }
};
class foo
{
public:
foo(std::shared_ptr<bar> barP) {}
};
int main() {
std::shared_ptr<foo> f;
std::cout << "before init " << std::endl;
std::shared_ptr<bar> b = std::make_shared<bar>();
f = std::make_shared<foo>(b);
std::cout << "after init" << std::endl;
}
The output of the above program -
before init
after init
destructor called
Generally, what is happening with your code is you are passing new bar to the constructor of foo. And no one is holding the ownership of bar shared pointer. So, the ref count is becoming 0 and it is being deleted, hence the destructor is being called.
Further Read: make_shared vs new
In ROS, there is a function called NodeHanle::subscribe(Args...): NodeHandle::subscribe. Which lets u pass a PRIVATE member function as callback.
However, when I tried it myself (passing private member function using std::bind), my compiler always fails and complaining about Foo::foo() is a private member function. When I change Foo::foo to public function, everything goes to normal.
template<typename T>
void getWrapper1(void(T::*fn)(int), T *t) {
return [&](int arg) {
std::cout << "process before function with wrapper" << std::endl;
(t->*fn)(arg);
std::cout << "process after function with wrapper" << std::endl;
};
}
void getWrapper2(std::function<void(int)> fn) {
return [=](int arg) {
std::cout << "process before function with wrapper" << std::endl;
fn(arg);
std::cout << "process after function with wrapper" << std::endl;
}
}
class Foo {
private:
void foo(int a) {
std::cout << __FUNCTION__ << a << std::endl;
}
}
int main(int argc, char** argv) {
Foo foo_inst;
auto func1 = getWrapper1(&Foo::foo, &foo_inst); // fail because foo is private
auto func2 = getWrapper2(std::bind(&Foo::foo, &foo_inst, std::placeholders::_1)); // fail because foo is private
func1(1);
func2(2);
return 0;
}
from this answer, using std::function can also passing private member function. But what I tried it different.
It worths to mention that in getWrapper2 I use [=] instead of [&] because using [&] may cause seg fault. Why it has to be a "value capture"?
platform: GCC 5.4.0, c++14, ubuntu16.04
You must pass it from the inside. You cannot access private function from the outside of the class. Not even pointer to private stuff. Private is private.
class Foo {
void foo(int a) {
std::cout << __FUNCTION__ << a << std::endl;
}
public:
auto getWrapper() {
// using a lambda (recommended)
return getWrapper2([this](int a) {
return foo(a);
});
// using a bind (less recommended)
return getWrapper2(std::bind(&Foo::foo, this, std::placeholders::_1));
}
}
Why it has to be a "value capture"?
Both wrapper need to value capture. Your Wrapper1 have undefined behaviour.
Consider this:
// returns a reference to int
auto test(int a) -> int& {
// we return the local variable 'a'
return a;
// a dies when returning
}
The same thing happen with a lambda:
auto test(int a) {
// we capture the local variable 'a'
return [&a]{};
// a dies when returning
}
auto l = test(1);
// l contain a captured reference to 'a', which is dead
Pointers are passed by value. A pointer is itself an object. A pointer has itself a lifetime and can die.
auto test(int* a) -> int*& {
// we are still returning a reference to local variable 'a'.
return a;
}
And... you guessed it, the same thing for std::function:
auto test(std::function<void(int)> a) {
// return a lambda capturing a reference to local variable 'a'.
return [&a]{};
}
I'm trying to create an example of binding a boost::function to a member function that goes out of scope. It is still possible to call this function, even though the object no longer exists.
I need to prove that it is not a correct use and the app needs to fail. But the memory location still seems to be in tact, so I need a way to make it fail.
The other question asked would be: am I right? Is there something I might be missing?
class bad_object {
public:
void fct1() {cout << "Fct 1 called. String value: " << sth << endl;};
void fct2(int i) {cout << "Fct 2 with param " << i << endl;};
string sth;
};
int main()
{
bad_object b;
boost::function<void ()> f1(boost::bind( &bad_object::fct1, b ));
boost::function<void ()> f2(boost::bind( &bad_object::fct2, b, 10 ));
boost::function<void ()> f3;
{
bad_object c;
c.sth = "There once was a cottage";
f3 = boost::bind( &bad_object::fct1, c );
}
// c now goes of scope, f3 should therefore be invalid
f3();
return 0;
}
output as expected.
Fct 1 called. String value:
Fct 2 with param 10
Fct 1 called. String value: There once was a cottage
Perhaps you use weak_ptr: Live On Coliru
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
struct X
{
int foo() const
{
return 42;
}
virtual ~X() {
std::cout << "I'm stepping out here\n";
}
};
int weak_call(int (X::*ptmf)() const, boost::weak_ptr<X> const& wp)
{
auto locked = wp.lock();
if (!locked)
throw boost::bad_weak_ptr();
return ((*locked).*ptmf)();
}
int main()
{
boost::function<int()> bound_foo;
{
auto x = boost::make_shared<X>();
bound_foo = boost::bind(weak_call, &X::foo, boost::weak_ptr<X>(x));
std::cout << "Bound foo returns: " << bound_foo() << "\n";
}
std::cout << "Bound foo returns: " << bound_foo() << "\n";
}
Prints:
Bound foo returns: 42
I'm stepping out here
terminate called after throwing an instance of 'boost::bad_weak_ptr'
what(): tr1::bad_weak_ptr
A more generalized version (that allows n-ary member function, optionally const-qualified) is here (requiring c++11): coliru