2017-12-09 7 views
9

は、私は現在、その一般的な構造のようになります小さなCプログラムをデバッグしようとしています。しかし、このブレークポイントでスタックフレームを調べると、変数buf_lenがローカルスコープで既に存在し、任意の(?)値を持つことさえあります。変数がこの関数の前のどこにでも宣言されていない場合、これはどのように可能ですか?宣言/割り当てを組み合わせる前にローカル変数を使用できますか?</p> <pre><code>int some_function(...) { ... size_t buf_len = some_other_function(...) ... } main() { ... int foo = some_function(...) ... } </code></pre> <p>私は(lldbを使用して)<code>some_function()</code>にブレークポイントを設定しました:

+0

スタックフレームには、ローカル変数や他のものに*および*で渡されたargsが含まれています。 – babon

+0

@babon関数でブレークポイントを設定することを誤解していますか?私はそれが基本的にスタックフレームが関数の引数を知っているはずだが、その関数で作成された新しい変数ではない、その関数の最初の行で停止するためのショートカットだと思った。それは間違っていますか? – user8793

+5

私のコンパイラコースを覚えている限り、スタックフレームのサイズはコンパイル時に計算されます。そのことから、 'buf_length'は既にスタックフレームに"予約された位置 "を持つ可能性があります。つまり、 'some_function'を呼び出すと、スタックフレームが割り当てられ(すなわちspが増加します)、lldbはすでに' buf_length'の位置を出力します。誰かによって確認されるために、これはちょうど推測です... – Bromind

答えて

10

§6.2.4/6 of the C11 Draft Standardによれば、可変長配列型を持たないようなオブジェクトについて

、 寿命は、そのブロックの実行中に終了するまで 関連付けられているブロックへのエントリから延びていますいずれにしても。

だから、buf_len瞬間の実行がsome_function()入るデバッガで表示されていることは驚くことではありません。

+0

私は実際にスタックフレームの作成を誤解していました。あなたの説明をお寄せいただきありがとうございます。 – user8793

+3

これは標準用です。しかし、変数が最適化されていれば、OPはスタックフレーム内に変数を見つけられないという驚きを得るでしょう。 –

+1

@Frankie_C - 私はあなたのポイントを見失う。 OPは期待されていないときに見える変数について尋ねられました。この回答はOPの投稿された質問に対処しています。スタックフレームに関する概念などは、いくつかのインスタンスで動作を説明するのに必要な可能性のある実装の詳細ですが、これは標準で実装されているすべての実装についてきちんと説明されています。 –

2

スタックフレームには、ローカル変数や他のものとともに渡されるargsが含まれています。 this、特に「構造」セクションをご覧ください。ブレークポイントでは、2つの機能の間で停止することはできません。関数呼び出しでは、スタックフレームが最初に作成されたものの1つです。

+0

これは実際には説明しません。変数が宣言されると、インプリメンテーションは変数のスペースを割り当てます(x86 *の場合、sizeof変数によってスタックポインタを減らすことになります)。実際には、すべての実装では、関数プロローグでローカルに一度にスペースを割り当てているだけです。 – Ruslan

5

コンパイル時に、各変数がシンボルテーブルに追加されます。 このため、変数への参照は、すでに宣言されていてシンボルテーブルに挿入されている場合にのみ解決されます。宣言の前に変数を参照すると、未定義参照のエラーが発生します。

しかし、すべての自動変数のスペースには、関数プロローグ中にスタック内にが割り当てられています(つまり、IA32-64アーキテクチャでは、すべての自動変数で必要なスペースは、スタックフレーム内のポインタレジスタ)。必要なスペースは、その関数のシンボルテーブルに存在するすべての自動変数に必要なメモリスペースを合計することによって、コンパイラによって計算されます。

実際にスタックフレームが関数入力時に作成されると、後で使用されてもすべての自動変数が存在します。

場合によっては、変数は割り当てられません。コンパイラがそれらを最適化する場合、コードを最適化するコンパイラは、変数を使用する別の方法を選択します(つまり、レジスタを使用するか、 。

関連する問題