2016-04-22 75 views
0

我想从我的ODE(打开动态引擎)模拟体对象返回浮法X,Y和Z角度值。警告:局部变量“角度”的地址返回[-Wreturn-本地地址]

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; 
} 

因为dBodyGetQuaternion回到4个常量浮点四元,我需要再拿到旋转和我已经试图让它来编译巨大的困难。现在它编译,但我得到这个警告。

任何人都可以向我解释为什么,请问这意味着什么?

+0

错误消息是相当清楚的。你将返回'angles'的地址,但是在你返回之后,'angles'不再存在。那么调用者应该如何处理不再存在的对象的地址? –

+0

好吧,感谢清理东西:) – Jade

回答

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

定义了一个本地数组。

声明

return angles; 

指针返回到该阵列的第一个元素。

但是,只要函数返回,数组就会被破坏。因此,返回的指针是一个悬挂指针。

这就是编译器警告你的。如果您在调用函数中取消引用了返回的指针,则会调用未定义的行为。

为了返回一个指针数组将保持在函数返回后有效,你需要动态分配内存,并返回动态内存。

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; 
} 

请记住,如果你做了以上,你就必须确保调用delete []在调用函数返回的指针。

为了避免手动分配和释放内存,你可以使用std::vector<float>为您的返回类型的麻烦。

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; 
} 

由此,内存管理自动完成。

由于阵列的尺寸固定为3,使用std::array<float, 3>比使用std::vectro<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; 
} 
+0

'array '可能是适当的,因为它似乎每次都返回相同的大小 –

+0

这很好,谢谢你的深入解释。过去几个月我一直只使用C++,但仍然对指针的工作方式感到困惑,因此非常感谢有用的建议。 – Jade

+0

@Jade,我很乐意提供帮助。快乐的编码。 –

1

警告说,究竟出了什么问题:你是返回一个指向本地阵列angles

局部变量,无所谓它们很简单int变量或像你这样的数组,在函数返回时超出范围。这意味着它们会消失。指向这样一个变量的指针意味着你不能再使用该指针,因为它不再指向变量所占用的内存。使用它将导致未定义的行为

有两个解决问题的方法:第一种方法是动态地分配使用new[]的阵列,并返回指针。分配到new[]的内存永远不会超出范围,直到您delete[]它。

第二个解决方案是定义在阵列主叫功能,和一个指针传递给它作为参数,并有你的功能填写英寸

由于我错过,这是一个C++的问题,我宁愿推荐第三种解决方案:使用std::array。然后,您可以在函数内部本地声明数组,并返回该对象,并且该对象和编译器将确保根据需要复制数据。

+0

这是一个C++的问题,所以malloc不应该真的被推荐 –

1

你需要坚持堆上的结果,使其生存的本地函数的返回:

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

float * angles = new float[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; 
}