c++ lambda executed at wrong address / in wrong context - c++

The following code is also available at godbolt.org/z/SjkAWZ.
I have a struct with a std::function as member variable, which gets assigned by a lambda expression in the constructor.
The lambda can be called from the constructor successfully, but not from a member function.
#include <vector>
#include <functional>
struct S
{
S()
{
std::cout << "construct: " << reinterpret_cast<long>(this) << " " << std::flush;
std::cout << m_ << '\n';
lambda_ = [&]() {
std::cout << "lambda: " << reinterpret_cast<long>(this) << " " << std::flush;
std::cout << m_ << '\n';
};
lambda_();
}
void foo()
{
std::cout << "foo: " << reinterpret_cast<long>(this) << " " << std::flush;
std::cout << m_ << '\n';
lambda_();
}
private:
int m_ = 3; // some member variable
std::function<void(void)> lambda_;
};
int main()
{
std::vector<S> v;
v.emplace_back();
v.emplace_back();
std::cout << "\n--- loop ---\n";
for(auto& b : v)
{ b.foo(); }
}
Possible program output:
construct: 94159000759920 3
lambda: 94159000759920 3
construct: 94159000761048 3
lambda: 94159000761048 3
--- loop ---
foo: 94159000761008 3
lambda: 94159000759920 0 // <-- bad *this* address, bad value for m_
foo: 94159000761048 3
lambda: 94159000761048 3 // <-- bad *this* address, correct value for m_ (coincidence?)
As you can see, the context this of the lambda function is wrong if it gets called from the member function foo.
Interestingly, this is not the case if I only emplace one element in the vector:
construct: 13753968 3
lambda: 13753968 3
--- loop ---
foo: 13753968 3
lambda: 13753968 3 // <-- correct *this* address and correct value for m_
I am using g++ version 8.3.0 on Debian.
Am I causing undefined behaviour by constructing the elements in the vector in place?

You missed the copy / move constructor for your struct!
If you assign some vars to a std::vector it will reserve sometimes new memory and copy all content to the new memory. In your case, the lambda is not aware about the change and keeps the reference to the old instance of S. So your code is simply broken.
You can work around the problem by reserving enough space before you assign content with:
int main()
{
std::vector<S> v;
v.reserve(5);
...
}
But this is only a work around! You should prepare a move/copy constructor to be able to get correct copies of your instances.

Related

C++ lambda capture list by value or by reference doesn't give me different results

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.

vector elements allocated on stack?

#include <iostream>
#include <vector>
using namespace std;
struct A {
int i = 0;
};
void append(vector<A>& v) {
auto a = v.back(); // is a allocated on the stack? Will it be cleaned after append() returns?
++a.i;
v.push_back(a);
}
void run() {
vector<A> v{};
v.push_back(A{}); // is A{} created on the stack? Will it be cleaned after run() returns?
append(v);
for (auto& a : v) {
cout << a.i << endl;
}
}
int main() {
run();
return 0;
}
The code above prints as expected:
0
1
But I have two questions:
is A{} created on the stack? Will it be cleaned after run() returns?
is a allocated on the stack? Will it be cleaned after append() returns?
Update:
#include <iostream>
#include <vector>
using namespace std;
struct A {
int i = 0;
A() { cout << "+++Constructor invoked." << endl; }
A(const A& a) { cout << "Copy constructor invoked." << endl; }
A& operator=(const A& a) {
cout << "Copy assignment operator invoked." << endl;
return *this;
};
A(A&& a) { cout << "Move constructor invoked." << endl; }
A& operator=(A&& a) {
cout << "Move assignment operator invoked." << endl;
return *this;
}
~A() { cout << "---Destructor invoked." << endl; }
};
void append(vector<A>& v) {
cout << "before v.back()" << endl;
auto a = v.back();
++a.i;
cout << "before v.push_back()" << endl;
v.push_back(a);
cout << "after v.push_back()" << endl;
}
void run() {
vector<A> v{};
v.push_back(A{});
cout << "entering append" << endl;
append(v);
cout << "exited append" << endl;
for (auto& a : v) {
cout << a.i << endl;
}
}
int main() {
run();
return 0;
}
Output:
+++Constructor invoked.
Move constructor invoked.
---Destructor invoked.
entering append
before v.back()
Copy constructor invoked.
before v.push_back()
Copy constructor invoked.
Copy constructor invoked.
---Destructor invoked.
after v.push_back()
---Destructor invoked.
exited append
0
0 // I understand why it outputs 0 here. I omitted the actual work in my copy/move constructors overloads.
---Destructor invoked.
---Destructor invoked.
I updated the code in my question, adding the copy/move constructors. I found copy constructor was called 3 times in append. I understand auto a = v.back(); needs a copy, But the two other copies maybe should be avoided?
The C++ specification doesn't actually say.
With v.push_back(A{}) the A{} part creates a temporary object, which is then moved or copied into the vector, and then the temporary object is discarded.
Same with local variables, really, the "stack" is actually never mentioned by the C++ standard, it only tells how life-time should be handled. That a compiler might use a "stack" is an implementation detail.
With that said, most C++ compilers will use the "stack" to store local variables. Like for example the variable a in the append function. As for the temporary object created for v.push_back(A{}) you need to check the generated assembly code.
For the life-times, the life-time of the temporary object A{} ends as soon as the push_back function returns. And the life-time of a in the append function ends when the append function returns.
In this function
void append(vector<A>& v) {
auto a = v.back(); // is a allocated on the stack? Will it be cleaned after append() returns?
++a.i;
v.push_back(a);
}
the variable a has the automatic storage duration and is a local variable of the function. It will not be alive after exiting the function.
In this function
void run() {
vector<A> v{};
v.push_back(A{}); // is A{} created on the stack? Will it be cleaned after run() returns?
append(v);
for (auto& a : v) {
cout << a.i << endl;
}
}
again the variable v has the automatic storage duration and is a local variable of the function. When the function will finish its execution the variable will be destroyed. And all elements of the vector (that are placed in the heap) also will be destroyed due to the destructor of the vector.
Consider the following demonstrative program.
#include <iostream>
#include <vector>
struct A {
int i = 0;
};
int main()
{
std::vector<A> v;
std::cout << "&v = " << &v << "\n\n";
A a;
std::cout << "&a = " << &a << "\n\n";
v.push_back( a );
std::cout << "&v = " << &v << '\n';
std::cout << "&a = " << &a << '\n';
std::cout << "&v[0] = " << &v[0] << "\n\n";
++a.i;
v.push_back( a );
std::cout << "&v = " << &v << '\n';
std::cout << "&a = " << &a << '\n';
std::cout << "&v[0] = " << &v[0] << '\n';
std::cout << "&v[1] = " << &v[1] << "\n\n";
return 0;
}
Its output might look like
&v = 0x7ffc27288dd0
&a = 0x7ffc27288dcc
&v = 0x7ffc27288dd0
&a = 0x7ffc27288dcc
&v[0] = 0x55725232ee80
&v = 0x7ffc27288dd0
&a = 0x7ffc27288dcc
&v[0] = 0x55725232eea0
&v[1] = 0x55725232eea4
As you can see the addresses of the vector v and the object a looks similarly because they are allocated in the same outer block scope of the function and have the automatic storage duration.
&v = 0x7ffc27288dd0
&a = 0x7ffc27288dcc
And they are not changed when new values are pushed on the vector.
However the addresses of the elements of the vector as for example
&v[0] = 0x55725232ee80
&v[0] = 0x55725232eea0
&v[1] = 0x55725232eea4
have a different representation and can be changed when a new elements are added to the vector because the memory for them can be dynamically reallocated.
EDIT: After you updated your question then take into account that when a new element is added to the vector the elements of the vector can be reallocated calling the copy constructor. You can use the method reserve to reserve enough memory to avoid its reallocation and the method emplace_back.
is a allocated on the stack?
There is no such thing as "stack" storage in the language. a has automatic storage.
As far as language implementations are concerned, this typically means that the variable is probably stored in a register, or on stack, or nowhere.
Will it be cleaned after append() returns?
Yes. Automatic variables are destroyed automatically when they go out of scope.
is A{} created on the stack?
A{} is a temporary object. The language is a bit vague about the storage class of temporary objects, but it is clear about the lifetime.
Will it be cleaned after run() returns?
In this case, the temporary object is destroyed at the end of the full expression, which is before run returns.
vector elements allocated on stack?
No. Vector elements are created in dynamic storage.
Update
But the two other copies maybe should be avoided?
If your endgoal is to get a vector with two elements, you can avoid all of the copies like this:
std::vector<A> v(2);

C++; using lambdas to conditionally expand a function within a class (seg fault with MWE)

I would like to use lambdas to conditionally expand the functionality of a function within a class. There is no problem doing this outside of the class scope (see example), but the minimal working example below leads to a segmentation fault when calling a function that has modified itself within the class. Can anyone explain why this code fails and how I should be thinking about lambdas within a class differently than lambdas outside of a class?
#include <functional>
#include <iostream>
class MyClass
{
public:
MyClass(bool modify);
int a;
std::function<void (void)> myFunc;
};
MyClass::MyClass(bool modify)
{
a = 2;
myFunc = [this](){ std::cout << "1. Inside my initialized function; a="
<< this->a << std::endl;};
//myFunc(); -- works with or without being commented
if (modify)
{
myFunc = [this](){ this->myFunc();
std::cout << "2. adding an output line to my "
<< "initialized function" << std::endl;};
//EDIT: Originally tried
// myFunc = [myFunc](){ myFunc(); std::cout << endl; };
// but this will not compile. See edit of post below
//myFunc(); -- fails with or without being commented
}
}
int main(int argc, char **argv)
{
std::function<void (void)> func;
int a = 2;
func = [a](){ std::cout << "1. Inside my initialized function; a="
<< a << std::endl;};
func = [func](){ func();
std::cout << "2. adding an output line to my initialized "
<< "function" << std::endl;};
std::cout << "Result of modified function outside of class: " << std::endl;
func();
std::cout << std::endl;
std::cout << "Result of unmodified function in class: " << std::endl;
MyClass myClassNoMod(false);
myClassNoMod.myFunc();
std::cout << std::endl;
std::cout << "Result of modified function in class: " << std::endl;
MyClass myClassMod(true);
myClassMod.myFunc();
return 0;
}
Edit PaulR gave the reasonable suggestion of capturing myFunc rather than this in the update of myFunc. In my original implementation this is what I tried:
myFunc = [myFunc](){myFunc(); std::out << "stuff\n"; };
but this lead to the compiler errors
error: 'myFunc' in capture list does not name a variable
myFunc = [myFunc](){ myFunc();
^
error: 'this' cannot be implicitly captured in this context
myFunc = [myFunc](){ myFunc();
In your class you capture the this pointer and not the previous value of myFunc, thus your lambda will recursively call itself forever, since at call time the myFunc member will be already changed to the new lambda.
In main you capture the previous value of func by value and thus it does what you expect.
So I would suggest capturing a copy of myFunc by value (i.e. without &) instead of this.
if (modify)
{
auto previousFunc = std::move(myFunc);
myFunc = [previousFunc](){ previousFunc();
std::cout << "2. adding an output line to my "
<< "initialized function" << std::endl;};
}
If you are using C++14 or newer you can also use lambda capture expressions to avoid making a copy and directly moving the previous function into the lambda capture:
if (modify)
{
myFunc = [previousFunc{std::move(myFunc)}](){ previousFunc();
std::cout << "2. adding an output line to my "
<< "initialized function" << std::endl;};
}

How to move a variable into a lambda expression?

I see the C++11 documentation (http://en.cppreference.com/w/cpp/language/lambda) for lambda expressions states capture by value and reference are supported but not rvalue reference. The closest SO question I could find related to this is: How to capture a unique_ptr into a lambda expression?, but it seems like my use case doesn't require the use of std::bind.
Code
#include <iostream>
#include <memory>
class Foo
{
public:
explicit Foo(int value = 0) : mValue(value) {}
// The following items are provided just to be explicit
Foo(Foo &&other) = default;
Foo &operator=(Foo &&other) = default;
Foo(const Foo &other) = delete;
Foo &operator=(const Foo &other) = delete;
~Foo() {}
int mValue;
};
void bar(std::unique_ptr<Foo> f)
{
std::cout << "bar: " << std::dec << f->mValue << "\n";
}
int main()
{
{
std::unique_ptr<Foo> f(new Foo(22));
std::cout << "main: " << std::hex << f.get() << "\n";
// Call the bar function directly (requires using std::move)
bar(std::move(f));
std::cout << "main: " << std::hex << f.get() << "\n";
}
{
std::unique_ptr<Foo> f(new Foo(99));
std::cout << "main: " << std::hex << f.get() << "\n";
// Lamda expression captures 'f' by reference and then calls the bar function (again, requires using std::move)
auto fn = [&f](){ bar(std::move(f)); };
fn(); // Execute the closure
std::cout << "main: " << std::hex << f.get() << "\n";
}
return 0;
}
Example Output
main: 0x92e010
bar: 22
main: 0
main: 0x92e010
bar: 99
main: 0
By examining the output it appears this program is running correctly (i.e., the observed results are what I expected. However, I have the following questions.
Questions
Is using the closure equivalent to the code that calls the bar function directly?
I'm asking explicitly since the documentation (see beginning of the question) about lambda expressions didn't state anything about using std::move on captured references (i.e., I want to make sure this doesn't run afoul of undefined behavior or similar bad outcomes).
If the answer to the first question is "you can't use std::move on the captured reference", then what is the right way to do this (e.g., the std::bind solution, etc)?
Is using the closure equivalent to the code that calls the bar function directly?
Yes, they're equivalent in this code. Captured references aren't special in any way that I can think of: you have fully defined behavior, as long as f is in scope and can be moved from.

get state in a function object casted to a std::function

I want to retrieve state from a function object. But the function object has been casted to a function<> template. How can I do it?
I mean:
function object:
class Counter {
private:
int counter_;
public:
Counter():counter_(0) {cout << "Constructor() called" << endl;}
Counter(int a):counter_(a) {cout << "Constructor(a) called" << endl;}
void operator()(int sum) {
cout << counter_++ + sum << endl;
}
int getCounter() { return counter_;}
};
In main. My first step is use object directly:
int main() {
Counter a(10);
a(0);
a(0);
cout << "Counter: " << a.getCounter() << endl;
Its shows:
Constructor(a) called
10
11
Counter: 12
It's ok and it's what I expected.
But in
Counter b(10);
function<void(int)> f = b;
f(0);
f(0);
cout << "Counter: " << b.getCounter() << endl;
It shows
Constructor(a) called
10
11
Counter: 10
Argh!, I supposed that f was a wrapper of real object so modifying f we really modify b. No: f has a copy of b, but I can't call to f.getCounter() so How can I get State (counter_ var) from f?
I can't use directly Counter class (in this example) because I have some other similar classes with same signature "void(int)" And I want to use them in indistinctly in a caller function.
I can avoid std::function template at all using a common base class for all my function object but I think there is a solution more C++11 with STL and templates...
So, Is there that solution?
Thanks
Create the function from a reference wrapper:
function<void(int)> f = std::ref(b);
giving the result:
Constructor(a) called
10
11
Counter: 12
Of course, you need to make sure that the function isn't invoked after the counter is destroyed.
If you need to access the counter from the function object, then use its target member:
if (Counter * c = f.target<Counter>()) {
std::cout << "Counter: " << c->getCounter() << '\n';
} else {
std::cout << "Not a counter.\n";
}
This is not a cast:
function<void(int)> f = b;
A std::function is been constructed, with a copy of your function object as its target.
You can either make the target a reference to your function object:
function<void(int)> f = std::ref(b);
Or let f contain a copy but then retrieve that copy from f:
Counter* c = f.target<Counter>();
cout << "Counter: " << c->getCounter() << endl;
It's usually safer to let f contain a copy as you don't ned to worry about the lifetime of b.