パスワードを忘れた? アカウント作成
この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。

C における一時オブジェクトの生存期間」記事へのコメント

  • by Anonymous Coward

    私なりにこの問題点を説明させていただきます。間違っていたらごめんなさい。結論から言うとメモリ領域を本来の意味から逸脱した状態で使っている瞬間があるからだと考えています。

    スタックは下に向かって伸びていくとしますので、スタックポインタより上が使用中、下が未使用と考えてください。

    1.addressee()に入った時にresultはスタック上に確保され初期化される。

    +--------------+
    |return address|←addressee()を呼び出した場所への戻り
    +--------------+
    |<-result      |
    |  a[world\0]  |
    +--------------+←スタックポインタ

    2.addressee()で使った領域を破棄し呼び出し元に戻る。

    • コメント付いているのに気付いてませんでした。

      その説明は誤りだと思います。2. の時点で既に領域が無効だ、という説明かと思いますが、その場合、同様の議論が struct ではなく int に対しても成立し以下のコードも誤りとなってしまいます(3. で持ってくるのはアドレスではなく値になりますが領域自体が無効なら議論は同じです)。

      int addressee(void) {
        int result = 5;
        return result;
      }

      int main(void) {
        printf("Hello, %d!\n", addressee());
        return 0;
      }

      さすがにこのコードが誤りだと関数の戻り値は全て使えないことになってしまいます。確かに result は関数内で確保されていますが値返しで返ってくるため再度スタック上に積まれて呼び出し側でも有効な状態で返ってきます。問題はそのスタック上の値がいつまで有効か、です。C99 規格上では次の副作用完了点まで有効ですので以下のコードは未定義動作を含みません(次の副作用完了点は printf 呼び出しなのでその前に a[0] の評価は完了する)。嫌な例でわざわざ f() 呼び出しが入っているのは別の副作用完了点を入れて問題を起こすため、です。

      int main()
      {
          printf("%c%c!\n", addressee().a[0]);
          return 0;
      }

      親コメント

人生の大半の問題はスルー力で解決する -- スルー力研究専門家

処理中...