Confused by lambda output in this case - c++

After learning lambda in C++11, I wrote this and got confused by the output.
auto f1 = [] () {
int tmp = 10;
int *tmp_p = &tmp;
return [tmp_p] (int x) {
return *tmp_p + x;
};
}();
auto f2 = []() {
int tmp = 10;
return [&tmp] (int x) {
return tmp + x;
};
}();
cout << f1(5) << endl;
cout << f1(5) << endl;
cout << f2(5) << endl;
cout << f2(5) << endl;
Output is:
15
5772973
2686617
2686617
What's the reason behind this?

Because undefined behavior.
tmp gets destructed after f1 is assigned, and so tmp_p becomes a dangling pointer. Anything can happen when you dereference it, including sometimes given the right value 15, and sometimes not 5772973.
The same goes for f2, but instead of using a pointer, you use a reference, which references a destructed object, which is also undefined behavior.

This is what we call undefined behavior. Why is your code causing undefined behavior?
First case: f1():
It's causing it, because after calling these lambdas the values of int tmp and int *tmp_p aren't on the stack anymore (the int *tmp_p was copied but the int tmp was removed).
Second case: f2(): The value of tmp was accessed by reference to the inner lambda. After the generating lambda finished it wasn't on the stack anymore and something obtained the memory and wrote garbage into it.

Related

Strange C++ output with boolean pointer

I have the following code:
#include <iostream>
using namespace std;
int main() {
int n = 2;
string s = "AB";
bool* xd = nullptr;
for (int i = 0; i < n; i += 100) {
if (xd == nullptr) {
bool tmp = false;
xd = &tmp;
}
cout << "wtf: " << " " << (*xd) << " " << endl;
}
}
When I run this on my own mac with g++ -std=c++17, I get a random integer every time (which is odd since *xd should be a bool). Weirdly enough, this doesn't happen on online IDEs like csacademy and onlinegdb.
if (xd == nullptr) {
bool tmp = false;
xd = &tmp;
}
tmp is an automatic variable. It is destroyed automatically at the end of the scope where the variable is declared. In this case, the lifetime of the object ends when the if-statement ends. At that point, the pointer xd which pointed to the variable becomes invalid.
(*xd)
Here, you indirect through an invalid pointer. That's something that a program must never do. The behaviour of the program is undefined. The program is broken. Don't do this.

The lifetime of a pointer reference in C++

I wrote some code that involves moving and changing variables in C++. Below is what I have wrote.
#include <iostream>
void six(int*& ptr) {
int s = 6;
ptr = &s;
}
int main() {
int f = 5;
int* ptr = &f;
std::cout << *ptr << '\n';
six(ptr);
if (ptr) {
std::cout << *ptr;
}
else {
std::cout << "null\n";
}
return 0;
}
so this prints:
5
6
I tried another code, adding a single line:
#include <iostream>
void six(int*& ptr) {
int s = 6;
ptr = &s;
free(&s); // added line
}
int main() {
int f = 5;
int* ptr = &f;
std::cout << *ptr << '\n';
six(ptr);
if (ptr) {
std::cout << *ptr;
}
else {
std::cout << "null\n";
}
return 0;
}
Obviously, this gives an error after printing 5 because what the modified pointer is pointing is not available when called the second time.
However, I am confused at the first case. When calling six in the main function, variable s is not in the main scope, but the value itself still continues to remain in the memory to be referenced. Doesn't C++ automatically destroy variables and clean them when it goes out of the scope? Is this a memory leak?
The first case is not a memory leak, but an undefined behaviour because your variable go out of scope.
In this case you don't know when the memory will be cleaned(replaced) o reallocated.
So in some case the result can be correct but it's a pure question of luck.

unique_ptr with array crash when calling reset

Can someone explain the crash here?
#include <iostream>
#include <memory>
int main() {
int *num1 = new int(5), *num2 = new int(18);
std::unique_ptr<int> numptr = std::unique_ptr<int>(num1);
std::cout << *numptr.get() << '\n'; // 5
numptr.reset(num2);
std::cout << *numptr.get() << '\n'; // 18
int a[5] = {0,2,4,6,8}, b[5] = {0,3,6,9,12};
std::unique_ptr<int[]> u = std::unique_ptr<int[]>(a);
std::cout << u[3] << '\n'; // 6
u.reset(b);
std::cout << u[3] << '\n'; // Crash. Why??? Should output 9, right?
}
There is no crash when calling reset with std::unique_ptr<int>, so why the crash with std::unique_ptr<int[]>. As I see it, u takes ownership of b, and then deletes a. So u[3] should be b[3] = 9 which should work fine because b is not deleted. What's going on here?
You wrap your unique_ptr around an array, which has automatic storage duration and its memory will be released by the runtime. At the end of your program, unique_ptr tries to release the same memory. Basically the line u.reset(b); is equivalent to delete[] a; // then set u to point to b.
If you try a simple program like
int main()
{
int arr[10];
delete[] arr; // runtime error here
}
you'll get exactly the same error. You should never use smart pointers with non-dynamic objects.

Undefined behavior of std::future as return type?

In my case, I use std::future as a return type but get a undefined behavior.
The code is below:
#include <future>
#include <iostream>
#include <pthread.h>
std::future<bool> update() {
int c = 1;
//std::cout << "?" << c << std::endl; // debug line
auto lambda = [&] () -> bool {
int b = 0;
for(int i = 0; i < 10000000; ++i) {
b += 1;
}
std::cout << "?" << c << std::endl;
return c == 1;
};
return std::async(std::launch::async, lambda);
}
int main(int argc, char *argv[])
{
auto f2 = update();
std::cout << f2.get() << std::endl;
return 0;
}
I compiled this piece of code by g++-4.7.2 -std=c++11 test_future.cc -lpthread and get the following output result:
?0
0
But when I uncommented the debug line above, the output became 1(as expected). Besides, if I use std::future as a parameter with update function in stead of return value, I can also get the right output result.
I want to know what's the problem here. The bug of g++ or the bug of the usage? Thanks.
The problem is that you capture the variable c by reference, combined with you running the lambda asynchronously. The last part means that the update function may have returned before the lambda actually runs, and it now has a reference to a variable that no longer exists.
The reason it seems to work if you have the debug line, is because of just undefined behavior.
So the problem doesn't have anything to do with you returning the std::future.
The obvious solution is of course to capture c by value instead, and if it's not possible in your actual code then you might have to rethink your design.
The issue is that your lambda auto lambda = [&] () -> bool is capturing by reference. The reference to c could be dangling, since the thread could execute after the function exits.
You should probably capture by value auto lambda = [=] () -> bool instead.
That looks like undefined behavior to me. You capture c by reference, but it will have fallen out of scope by the time lambda executes.
Therefore c == 1 is undefined behavior, because c has fallen out of scope. If you capture by value you should be fine.
auto lambda = [c] () -> bool {
int b = 0;
for(int i = 0; i < 10000000; ++i) {
b += 1;
}
std::cout << "?" << c << std::endl;
return c == 1;
};

Stack memory allocation

It is being said that local variable will be allocated and deallocated automatically when function ends in C/C++.
According to my understanding, when having been deallocated, the value held by local variable also be destroyed!!! Please correct me if i'm wrong
Consider following code:
void doSomething(int** num)
{
int a = 10;
*num = &a;
} // end of function and a will be destroyed
void main()
{
int* number;
doSomething(&number);
cout << *number << endl; // print 10 ???
}
Could anybody clarify for me?
You are correct. your cout may or may NOT print 10. It will invoke undefined behavior.
To make a bit more of a note, try running the following code under your compiler with no optimizations enabled.
#include <iostream>
using namespace std;
void doSomething(int** num)
{
int a = 10;
*num = &a;
}
void doSomethingElse() {
int x = 20;
}
int main()
{
int* number;
doSomething(&number);
doSomethingElse();
cout << *number << endl; // This will probably print 20!
}
In this case, the integer a is on the stack. You are returning the address of that variable to the main program. The value at that address location after the call is undefined. It is possible in some situations that it could print 10 if that portion of the stack was not overwritten (but you certainly would not want to rely on it).
The content of the memory isn't actually destroyed.
For this case, num will point to a location which isn't being allocated for any variable, but it will hold it's content, which was set to 10.
The memory being pointed to has been released back to the system. That means that it will hold whatever value it had until the system assigns that block of memory to another variable and it gets overridden with a value.
Local variables are released when they go out of scope. If you are trying to return a value using an out parameter to a function:
void doSomething(int** num)
{
int* a = new int;
*a = 10;
*num = a;
}
int main()
{
int* number = 0;
doSomething(&number);
std::cout << *number << std::endl; // print 10 ???
if (number) delete number;
}
Though, for something this simple, you are better off just doing this:
int doSomething()
{
return 10;
}
int main()
{
std::cout << doSomething() << std::endl;
}