Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

warning: address of local variable 'angles' returned [-Wreturn-local-addr]

I'm trying to return float x, y and z angle values for a body object from my ODE (open dynamics engine) simulation.

float* Creature::eulerAngles(const float &q0, const float &q1, const float &q2, const float &q3){

    float angles[3] = {atan2(2 * (q0*q1 + q2*q3), 1 - 2 * (q1*q1 + q2*q2)),
                      asin( 2 * (q0*q2 - q3*q1)),
                      atan2(2 * (q0*q3 + q1*q2), 1 - 2 * (q2*q2 + q3*q3))};
    return angles;
}

Because dBodyGetQuaternion returns 4 const float quaternions I need to then get the rotations and I've had immense difficulty trying to get it to compile. Now it does compile but I'm getting this warning.

Could anyone explain to me why and what it means please?

like image 771
Jade Avatar asked Apr 22 '16 04:04

Jade


People also ask

How do I fix function returns address of the local variable?

Solution. Since the problem is that the return address is actually of a local variable, the solution would be to dynamically allocate memory to a variable to hold the address and pass it to the function as a parameter. Now, the variable is declared outside the function block and is no longer a local variable.

Can we return address of local variable?

a is an array local to the function. Once the function returns it does not exist anymore and hence you should not return the address of a local variable.

How can a function return a local variable?

C++ How to return a local variable from a function? But there is a way to access the local variables of a function using pointers, by creating another pointer variable that points to the variable to be returned and returning the pointer variable itself.


1 Answers

float angles[3] = { ... };

defines a local array.

The statement

return angles;

returns a pointer to the first element of the array.

However, the array is destructed as soon as the function returns. Hence, the returned pointer is a dangling pointer.

That's what the compiler is warning you about. If you dereference the returned pointer in the calling function, you invoke undefined behavior.

In order to return a pointer to an array that will remain valid after the function returns, you need to allocate dynamic memory and return the dynamic memory.

float* Creature::eulerAngles(const float &q0, const float &q1,
                             const float &q2, const float &q3)
{
   float* angles = new float[3];
   angles[0] = atan2(2 * (q0*q1 + q2*q3), 1 - 2 * (q1*q1 + q2*q2));
   angles[1] = asin( 2 * (q0*q2 - q3*q1));
   angles[2] = atan2(2 * (q0*q3 + q1*q2), 1 - 2 * (q2*q2 + q3*q3));

   return angles;
}

Keep in mind that if you do the above, you'll have to make sure to call delete [] on the returned pointer in the calling function.

To avoid the hassles of manually allocating and deallocating memory, you can use std::vector<float> as your return type.

std::vector<float> Creature::eulerAngles(const float &q0, const float &q1,
                                         const float &q2, const float &q3)
{
   std::vector<float> angles(3);
   angles[0] = atan2(2 * (q0*q1 + q2*q3), 1 - 2 * (q1*q1 + q2*q2));
   angles[1] = asin( 2 * (q0*q2 - q3*q1));
   angles[2] = atan2(2 * (q0*q3 + q1*q2), 1 - 2 * (q2*q2 + q3*q3));

   return angles;
}

With this, memory management is done automatically for you.

Since the size of the array is fixed at 3, using std::array<float, 3> is better than using std::vector<float>:

std::array<float, 3> Creature::eulerAngles(const float &q0, const float &q1, const float &q2, const float &q3)
{
   std::array<float, 3> angles;
   angles[0] = atan2(2 * (q0*q1 + q2*q3), 1 - 2 * (q1*q1 + q2*q2));
   angles[1] = asin( 2 * (q0*q2 - q3*q1));
   angles[2] = atan2(2 * (q0*q3 + q1*q2), 1 - 2 * (q2*q2 + q3*q3));

   return angles;
}
like image 95
R Sahu Avatar answered Nov 05 '22 11:11

R Sahu