1. ホーム
  2. c++

[解決済み] 警告: ローカル変数 'angles' のアドレスが返されました [-Wreturn-local-addr] 。

2022-02-12 07:04:20

質問

ODE(オープンダイナミクスエンジン)シミュレーションで、ボディオブジェクトのx、y、z角度の値をfloatで返そうとしています。

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 quaternionsを返すので、回転を得る必要があるのですが、これをコンパイルするのに非常に苦労しました。今はコンパイルできるようになりましたが、このような警告が表示されます。

どなたか、その理由と意味を教えていただけませんか?

解決方法は?

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