Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why passing std::move(object) and member of this object to function causes SIGSEGV [duplicate]

The following code results in SIGSEGV and I cannot understand why is that.

#include <iostream>
using namespace std;

struct C {
    C(int x) { ptr = new int(x); }
    C(C&& c) { ptr = c.ptr; c.ptr = nullptr; }

    int* ptr;
};

void foo(int* x, C c) {
    cout << *x  << endl;
}

int main() {
    C c(10);
    foo(c.ptr, std::move(c));   
    return 0;
}

I would expect the pointer c.ptr to be passed by value to the function foo, however it behaves like its passed by reference.

Now, if I change the ordering of arguments: void foo(C c, int* x), than the problem disappears. The other solution is to create a local copy of c.ptr before calling to x, and than passing that local copy to foo.

I would like to understand why can't i pass c.ptr by value in the sample code above.

like image 241
Buyuk Avatar asked Jan 03 '23 01:01

Buyuk


1 Answers

It is passed by value, however:

foo(c.ptr, std::move(c));

It is unspecified in which order the parameters that are passed to a function call get evaluated.

Order of evaluation of the operands of almost all C++ operators (including the order of evaluation of function arguments in a function-call expression ... ) is unspecified.

"Unspecified" means that they can be evaluated in any order. The order can even be different each time you run the program. Your compiler chose to generate code that evaluates the 2nd parameter with the std::move first. As such, your move constructor moves the pointer out of the object, setting it to null. Then, c.ptr gets evaluated, passing the now-null pointer by value.

like image 73
Sam Varshavchik Avatar answered Jan 05 '23 14:01

Sam Varshavchik