電子書籍の厳選無料作品が豊富!

 関数の戻り値で変数を初期化すると、予期せぬ動作をする可能性があると聞いたのですが、実際にそのようなことがあるのでしょうか? また、予期せぬ動作をする場合、そのような現象が起きる環境と原因は何なのでしょうか?
 
 使用している言語はC++なので、例えば下のような動作です。
  int a = f();
  ・対象の関数が標準関数かどうかは不明です。
  ・変数はローカルを想定しています。

 ちなみに私は、C,C++を2,3年勉強しており、会社での実践経歴が1年程度です。

A 回答 (5件)

いや, いくらなんでも「古い規格の問題」はないと思います. #1 で指摘されている「最適化のしすぎ」というバグの可能性はあると思いますが, さすがにこの程度なら「普通に想定できる」挙動しかしないはずです.


#1 の指摘はぶっちゃけバグなので, 「初期化のときには問題だが代入では期待した通り」ということがあってもおかしくはありません.
    • good
    • 0
この回答へのお礼

 ご指摘ありがとうございます。早合点してしまいました。
 やはり、コンパイラのバグという線が有力ですかね。しかし、本当にそんなバグを持ったコンパイラがあったのか……、謎ですね。

お礼日時:2011/03/26 11:03

No.2で回答した者です



> この現象について話していた人に再び聞いてみました。それによると、宣言時に代入した場合、
> 変数の値はコンパイラ依存となり、不定となることがあるらしいです。

私も、年齢的には、話の大元の方と近い物がありますが、このような現象は聞いたことは無いですね。
よくは分かりませんが、何らかの目的で、言語仕様と異なる仕様の処理系があったということなのか、単にバグのある処理系での話ってことなんですよね。
    • good
    • 0
この回答へのお礼

 回答ありがとうございます。
 うーん、明確な原因は分からないままですね。確実なことは、「過去にたまたまそういう事例があっただけで、特に気にする必要はない」というぐらいでしょうか。

お礼日時:2011/03/26 11:23

少なくとも「現在の C++ の規格に従っている処理系」であれば問題ありません.



そもそも規格の中に「関数の返り値によって初期化している」例がある.
    • good
    • 0
この回答へのお礼

 回答してくださり、ありがとうございます。
 なるほど、コンパイラではなく、実は古いC++の規格が問題だったという可能性もありますね。だとすると、戻り値で初期化したときの変数値を意識したプログラミングは、必要ないような気がしてきました。

お礼日時:2011/03/24 09:13

質問に対して質問をして大変申し訳ないです



1)この現象は、特定の環境で発生するのでしょうか?
特定のOS、特定のコンパイラ/リンカ、またはコンパイラやリンカのオプション等

2)予期せぬ動作とは、正常動作の中での不整合でしょうか?
例えば、一見正常動作しているが、実行後のfの戻り値とaの値が不一致等

3)もしくは、例外が発生したり、プログラムが異常終了してしまうとかでしょか?

上記のようなコードで、特に問題になった記憶がないのでチョット気になり質問しました。
ただ、言語仕様上は問題ないと思うので、コンパイラのバグ等も考えられるかもしれないですね。


思いつくのは、スタックが足りなくて自動変数aの領域や、fの呼び出しに失敗している場合。
ただ、この場合だと自動変数の宣言、もしくは関数呼び出しのどちらかだけでもアウトですね。

この回答への補足

 この現象について話していた人に再び聞いてみました。それによると、宣言時に代入した場合、変数の値はコンパイラ依存となり、不定となることがあるらしいです。しかし、どのコンパイラでその現象が起きたのかは覚えていないとのこと。
 推測ですが、その人は40代ぐらいなので、古いコンパイラなのだと思います。ちなみに、私が使用しているVC++2005では問題なく動作します。
 なぜ私がここで質問したかというと、ほかにも同様の現象を体験している方がいるのか知りたかったからです。そのため、もう何日間かは回答を受け付ける状態にしておきます。

補足日時:2011/03/22 22:33
    • good
    • 0

私が25年くらい前に経験した事象は以下の通りです。


int a = f();
int b = f();
関数fは乱数や時刻要素から戻り値を得るものです。
よって、a != b が期待値ですが、a == b になりました。
この時、最適化をマックスにしてありました。
機械語を調べると、aに代入する時はfを呼び出して
いますが、bへの代入時には前の戻り値を流用しており、
関数は呼び出していませんでした。最適化を抑制すると、
当然ながら事態は改善されました。
当時は関数の行数やメモリ量により、最適化が微妙に
変化したのですが、最近ではメモリ量が飛躍的に増加
しており、代々の改良で誤動作を起こす確率も減ったと
思われます。尚、変数の定義と初期化のみならず、
最適化を最大にして、ステップ数の多いルーチンを
コンパイルした場合に危険が伴うようです。
    • good
    • 0
この回答へのお礼

 回答してくださり、ありがとうございます。

 一点だけ気になるのが、nda23さんによる説明だと、宣言のとき以外の代入でも同様の現象が起きるように思われます。私が聞いた内容は、初期化(宣言のときに代入)によって起こる現象だとのことです。(ですが、この話をした人が"代入"と"初期化"の違いを認識していない可能性もあります。)
 しかし、コンパイラによる最適化で予期せぬ動作をすることはあるので、私が聞いた内容に関係している可能性は高そうです。

お礼日時:2011/03/21 23:06

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報