Reputation: 1076
I'd like to return an Eigen::Vector from a function and wondering what's the proper way to do it. Something like
Eigen::VectorXd& getMesh(int N) {
Eigen::VectorXd mesh(N + 1); // nb. of nodes
// Nodes are equally spaced
for (int i = 0; i < N + 1; i++) {
mesh[i] = i * (1.0 / N);
}
return mesh;
}
int main() {
// Mesh with 100 cells
Eigen::VectorXd mesh = getMesh(100);
return 0;
}
Now of course, we might get into problems here since the memory used to create the mesh vector in getMesh() might not be dynamically allocated i.e. when we return from the function, out reference "points" to deleted memory.
I could allocate the memory inside the main function and then pass it to the getMesh function, but is that considered fine? What other possibilities would I have?
Upvotes: 3
Views: 2017
Reputation: 3677
You must not return a reference to a local variable of your function. This is called a dangling reference. Note that your compiler should give you a warning when you do this : e.g Visual Studio.
warning C4172: returning address of local variable or temporary: mesh
The problem with your current getMesh()
function is that the local variable mesh
gets allocated on the stack in the function execution. Then you return a reference to it in main
, but the stack memory where mesh
was allocated is freed when the getMesh()
function exits. This means it will very likely get overwritten by later data in your program.
Note that this issue will happen even if the memory used to store the coordinates stored in your vector. Your mesh
variable is an instance of a class (VectorXd
) with several member variables. One of them will be the size of your vector, and the other a pointer to the dynamically-allocated storage for your vector's data.
This is an example of what VectorXd
's definition could look like
class FakeVectorXd {
int current_size;
int max_size;
double* data;
};
When you create mesh
, the member variables current_size
, max_size
and data
are allocated locally on the stack. Then in the vector's constructor data
's value is set to point to a dynamically allocated memory area to store your vector's coordinates. When you return from getMesh()
, the stack location where current_size
, max_size
and data
live in memory is now marked as available and they will be overwritten.
What you can do is simply return the VectorXd
by value. This is perfectly fine:
Eigen::VectorXd getMesh(int N) {
Eigen::VectorXd mesh(N + 1);
for (int i = 0; i < N + 1; i++) {
mesh[i] = i * (1.0 / N);
}
return mesh;
}
Upvotes: 5