2012-01-05 12 views
13

は、私は、次の2つの機能を持っていると言います最初のもの(例えば、関数はローカル変数のアドレスを返します)しかし、私はこれは不正です。bがスタックから消えて、未定義のメモリへのポインタが残っています。リターンアドレスが

したがって、一時的な値のアドレスを返すときは、いつ慎重にする必要がありますか?

答えて

17

最初のスニペットで警告が表示されないのは、(コンパイラの観点から)ローカル変数にアドレスを返さないためです。

int * tempの値が返されます。この変数はローカル変数のアドレスである値(この例では)を含んでいても、コンパイラはコード実行スタックを上がらず、このような場合があるかどうかを確認します。

スニペットの両方があなたのコンパイラは、元について警告していなくても、同じように悪いです。この方法を使用しないでください。


ローカル変数にアドレスを返すときには、常に注意する必要があります。原則として、は決してと言えるでしょう。

static変数はまったく異なるケースですが、これはthis threadで議論されています。

+1

ありがとう!実際には、メインで戻り値を出力すると正しい結果が得られますが、それは実際には迷惑メールを出力することを意味しますか? – mary

+3

これは、あなたが通常「* [未定義の振る舞い](http://en.wikipedia.org/wiki/Undefined_behavior)*」と呼んでいることを意味します。標準で指定されていない動作。 –

-2

これらはどちらも悪いものです。両方の状況を検出して警告するには、優れたコンパイラが必要です。警告レベルを最大(常にとにかく)にして最適化をオンにすると、より良い結果が得られる場合があります。

+0

具体的なケースは多分です。しかし、コンパイラが単に検出することができない他の変数(または他の関数を介して)との間でアドレスを入れ替えることを含む類似のケースがたくさんあります。また、最適化はそのような問題を検出する機会を増加させることはめったになく、問題が観察可能な影響を及ぼす可能性が高くなります。 – Rob

+0

もちろん、コンパイラが検出できない状況がありますが、これらの特定のケースは簡単に検出可能でなければなりません。最適化は、最初の例を2番目の例に減らすために機能します。 – harald

+1

申し訳ありませんが、真実ではありません。コンパイラの実装品質については、「やるべきことはほとんどありません」 - 開発者の先入観に合わない独自のコスト/利益分析に基づくベンダーの決定です。また、ポインタを変更する可能性のある関数呼び出しなどの例を構築することも非常に簡単です。これは、実行可能ではない可能性がある最適化を意味し、与えられたものではなく、そのようなものを最適化するかどうかの仕入先決定にもなります。 – Rob

0

どちらの例も同様に正しくありません。私の推測では、あなたのコンパイラは危険を認識しないため、一時変数にアドレスを格納するときに警告を出しません。

1

mallocによって動的に割り当てられた場合は、ローカル変数を返すことができますが、その場合は変数を格納するために使用されるメモリがスタックにあるがヒープ上にあり、クリアされない自動ローカル変数(mallocなしで作成された)の場合に関数が終了した後に再利用されますか?

0

この質問はおそらくStackOで最も議論されているものの1つです。私が面白いと思ったStackOの同様のスレッドからの2つの返答は以下の通りです。おそらく、私が間違った(未定義の振る舞い)を非常にスリムにしているにもかかわらず、ローカル変数を逆参照するという悪い習慣を残しました。

Here is a simple answer

私は特にこの返信を言っています。

Here is an example where this bad practice caused some real hardware damage

関連する問題