2017-10-04 1 views
2
上のC++のforループ

I以下の機能を持っている:私が戻ると奇妙な行動マック

hej1025849 
hej1025850 
hej1025851 
hej1025852 

:私は無限ループを持っvector<vector<Surfel>>を返すのを忘れて

std::vector<std::vector<Surfel>> testAddingSift(
     const Groundtruth &groundtruth, 
     SurfelHelper &surfelHelper) { 
    for (int k = 0; k < 10; k++) { 
     std::cout << "hej" << k <<std::endl; 
    } 
} 

もちろん

hej0 
hej1 
hej2 
hej3 
hej4 
hej5 
hej6 
hej7 
hej8 
hej9 

が、それはベクトルを返すために忘れてミスをしましたが、なぜです:vector<vector<Surfel>>私が取得します-loopは影響を受けますか?

私はMacBook ProをSierraとCLionで使用していますが、これはclangだと思います。

+8

未定義の動作は不思議な仕方で動作します。 – Borgleader

+1

あなたのループは '' hej "'を文字列に続く数字なしで10回印刷しなければなりません。ループを正しくコピーしましたか? – dasblinkenlight

+0

定義されていない動作が_anything_にできる –

答えて

8

void以外の戻り値の型から返されない関数は、undefined behaviorです。そのようにすることで、定義上、結果として起こる行動を推論することはほとんど不可能になります。これは、未定義のビヘイビアが発生すると予想されるポイントの前にあるコードの動作に影響を与える可能性があります。

+0

おかげさまで、私はこれまで見たことがないので、少し混乱しました。私は何かを返すのを忘れるのは初めてではないが、それはこれまでにこの種の問題を引き起こしたことはない。 –

+3

@El_Loco未定義の動作に関する最悪の事の1つは、時には動作するように見えることです。定義されていない動作の結果、予期した動作を含む動作が発生する可能性があります。それはしばらくの間は検出されず、明白な理由がなくいつでも突然停止することがあります。これにより、そうでないときに何かが有効なC++であると信じることさえできます。 –

+1

コンパイラは、未定義の動作が発生しないと想定することは自由です。1つの可能性は、コンパイラは実行が決して関数の終わりに到達しないと想定していました。これは決して起こらないと思われる未定義の動作を引き起こすからです。 'for'ループの条件が常に偽である場合、関数の終わりに達するので、条件が単に真であると仮定することもできます。ループの比較を最適化し、無限ループにすることができます。しかしこれはただ一つの可能​​性です*。もっと多くのものがあるかもしれません。 –

1

正当な答えは、これはもちろん、未定義の動作であるため、何かが起こる可能性があるということです。もっと興味深いのは、世界でどのように返事を忘れるような愚かなことが無限ループにつながるかということです。

私が何かを返すことを忘れたのは初めてではありませんが、これまでにこの種の問題が発生したことはありません。

あなたが見ている結果は、オブジェクトには価値のないオブジェクトが返されることです。あなたのケースでは、コピーコンストラクタはネストされた配列を処理する必要があるので、自明ではありません。特に、戻り値の型をintに変更すると、無限ループがなくなると思われます(ただし、動作は未定義のままです)。

私の推測では、あなたのループがoperator <<を呼び出すときにスタックにリターンアドレスが置かれると思います。 operator <<が返ると、スタックフレームは使用されなくなりますが、その内容はそのまま残ります。私は、返されたベクトルをコピーするためのコードは、 "ゴミ"スタックフレームの内容をたくさんの要素を持つベクトルとして再解釈し、配列要素をコピーするのではなく、ループの本体を呼び出すと考えています。

これは1つの可能性に過ぎません。何が起こっているのかを知りたいのであれば、適切な方法は分解を掘り下げることです。