3
#include <iostream>
#include <string>
using namespace std;

string
crash()
{

}

int
noCrash()
{

}

int
main()
{
    crash(); // crashes
    // noCrash(); // doesn't crash
    return 0;
}

関数 crash() は Mingw g++ 4.6.2 でクラッシュし、関数 noCrash() は問題なく実行されます。文字列を返す関数が return ステートメントなしでクラッシュするのはなぜですか?

4

4 に答える 4

7

どちらも未定義の動作であり、noCrashクラッシュする可能性もあります。

于 2012-06-19T07:12:22.417 に答える
7

標準 6.6.3/2 から

式のない return ステートメントは、値を返さない関数、つまり戻り値の型が void の関数、コンストラクタ (12.1)、またはデストラクタ (12.4) でのみ使用できます。非 void 型の式を含む return ステートメントは、値を返す関数でのみ使用できます。式の値が関数の呼び出し元に返されます。式は、それが現れる関数の戻り値の型に暗黙的に変換されます。return ステートメントには、一時オブジェクト (12.2) の作成とコピーが含まれる場合があります。 関数の最後を流れることは、値を持たない戻りと同じです。これにより、値を返す関数で未定義の動作が発生します

于 2012-06-19T07:14:08.293 に答える
6

これの多くは定義されていませんが、そのような観測の実際的な理由を理解するのに役立つことは間違いありません。トラブルシューティングや、パフォーマンスや空間設計にも役立ちます。

したがって、実用的な意味では、関数が値を返さない場合、基本的には、呼び出し元がその値を期待するレジスタまたはメモリを設定できていません。かつてそこにあったゴミは何でも戻ってくるようです。戻り値の型が int の場合、ガベージ値を取得したことになりますが、文字列の場合は、文字列がテキスト値と場合によってはいくつかの参照カウンターまたはその他の管理データ。プログラムの後半で、呼び出し元のコードはポインターを削除して、そのヒープ メモリの割り当てを解除しようとします。ガベージ値を持つポインターを削除すると、プログラムがクラッシュする可能性が非常に高くなります。

于 2012-06-19T07:34:41.963 に答える
4

おそらく、コンパイラを呼び出すと、作成されたことのない一時オブジェクトcrashを破棄しようとするためです。std::string

両方の関数の動作が未定義であるため、憶測はやや無駄です。

于 2012-06-19T07:13:40.623 に答える