警告:返回的局部变量“角度”的地址 [-Wreturn-local-addr]

Posted

技术标签:

【中文标题】警告:返回的局部变量“角度”的地址 [-Wreturn-local-addr]【英文标题】:warning: address of local variable 'angles' returned [-Wreturn-local-addr] 【发布时间】:2016-08-15 13:19:08 【问题描述】:

我正在尝试从我的 ODE(开放动态引擎)模拟中返回身体对象的浮点 x、y 和 z 角度值。

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 个 const float 四元数,所以我需要进行旋转,而且我很难编译它。现在它确实编译了,但我收到了这个警告。

谁能给我解释一下为什么以及这意味着什么?

【问题讨论】:

错误信息很清楚。您正在返回angles 的地址,但在您返回后,angles 不再存在。那么调用者应该如何处理一个不再存在的对象的地址呢? 好的,感谢您的整理:) 【参考方案1】:
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&lt;float, 3&gt;比使用std::vector&lt;float&gt;要好:

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;

【讨论】:

array&lt;float, 3&gt; 可能是合适的,因为似乎每次都返回相同的大小 这很好,感谢您的深入解释。过去几个月我才使用 C++,但仍然对指针的工作方式感到困惑,因此感谢这些有用的建议。 @Jade,我很乐意提供帮助。编码愉快。【参考方案2】:

您需要将结果粘贴到堆上,以便它在本地函数的返回中存活:

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;

【讨论】:

【参考方案3】:

警告说明了问题所在:您正在返回一个指向本地数组 angles 的指针。

局部变量,不管它们是简单的int 变量,还是像你这样的数组,当它们的函数返回时就会超出范围。这意味着它们会消失。拥有指向此类变量的指针意味着您不能再使用该指针,因为它不再指向该变量占用的内存。使用它会导致未定义的行为

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

第二种解决方案是在调用函数中定义数组,并将指向它的指针作为参数传递给你的函数。

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

【讨论】:

这是一个 C++ 问题,所以不建议使用 malloc

以上是关于警告:返回的局部变量“角度”的地址 [-Wreturn-local-addr]的主要内容,如果未能解决你的问题,请参考以下文章

警告:函数返回局部变量的地址 [默认启用] [重复]

使用 C 字符串给出警告:“与返回的局部变量相关的堆栈内存地址”

为啥 c++ 编译器不会警告返回对局部变量的引用?

直接使用运算符的地址与使用指针变量返回局部变量的地址

C语言 怎么返回一个数组

函数返回局部变量