マクロ対応言語はどのようにしてデバッグのソースコードを追跡しますか?
-
13-09-2020 - |
質問
これはマクロに関するより理論的な質問です(私は思う)。私はマクロがソースコードを取得し、それを評価せずにオブジェクトコードを作成し、プログラマがより多用途の構文構造を作成することを可能にすることを可能にします。これら2つのマクロシステムを分類しなければならなかった場合、私は "Cスタイル"マクロと "Lispスタイル"マクロがあったと思います。
実行時に実際に実行されているコードはソースと異なるため、マクロのデバッグを少しトリッキングできるようです。
前処理されたソースコードの観点から、デバッガはプログラムの実行をどのように追跡しますか?マクロに関する追加のデータをキャプチャするように設定する必要がある特別な「デバッグモード」はありますか?
Cでは、デバッグ用のコンパイルタイムスイッチを設定することを理解できますが、Lispのいくつかの形式などの解釈言語はどうなりますか?
これを試していないことをお詫び申し上げますが、Lispツールチェーンは私が把握するために費やす必要があるよりも多くの時間を必要とする。
解決
私は、「Cスタイル」と「Lisp Style」マクロの根本的な違いがあるとは思わない。コンパイラ適切な前にソースを変換します。大きな違いは、CのマクロがCプリプロセッサ(主に単純な文字列置換のためのより弱い二次言語)を使用しているため、LispのマクロはLisp自体で書かれています(そしてそれ故に全く何もすることができます)。
(脇の字として:私はしばらくの間非コンパイルされたLispを見ていません...確かに世紀の変わり以来ではありません。しかし、解釈されているものがマクロのデバッグの問題を容易にするように思われるでしょう。もっと多くの情報があるので、より難しい。)
私はMichaelに同意します:私はマクロを扱うCのためのデバッガをまったく見ていません。マクロを使用するコードは、何が起こる前に変換されます。 「デバッグ」モードCコードは一般に
-
自分自身あなたが行く前にそれをどこかで使う前に、Lispには機能があります それはCよりも簡単になる、 例えば、答えと
macroexpand-1
( C. 明らかに道があります Macroexpandファイル全体、AT 一度)。あなたは見ることができます マクロXPANSIONの前後の前後 あなたが書くとき、あなたの編集者の中で それ。
使用するプログラムのデバッグ マクロ、Lispはほとんど同じです ここでのCとして:あなたのデバッガーはを見ます マクロではなくコンパイルされたコード 応用。通常はマクロです 簡単でデバッグしました 使用する前に独立して、 これに対する必要性、c。
マクロをデバッグするための へのデバッグ<にマクロ定義自体が役に立つという状況にまたがっていたときはいつでも覚えていません。マクロ定義のバグでは、macroexpand-1
が問題をすぐに分離するか、その下のバグです。その場合、通常のデバッグ機能は正常に機能し、私の呼び出しの2フレームの間でマクロ秘密が発生したことを気にしないスタック。
他のヒント
マクロを使用してコードをデバッグするために、ラケットの種類のサポートを本当に見るべきです。このサポートには、Kenの表現が2つの側面があります。一方ではマクロのデバッグの問題があります。一般的なLispでは、マクロフォームを手動で拡大することです。 CPPを使用すると、状況は似ていますが、より原始的です - CPP拡張のみを通してコードを実行し、結果を調べます。ただし、これらの両方が多数のマクロにとって不十分であり、これはマクロを持つための動機でした。 Debugger ラケットの「構文拡張」ステップを1つずつ表示します。束縛された識別子などのものに追加のGUIベースの表示があります。
マクロを使用して、ラケットは常に他の方式やLISP実装よりも進んでいます。アイデアは、(構文オブジェクトとして)各式がコードにソースの場所を含む追加のデータであることです。このようにして、フォームがマクロの場合、マクロからの部品を持つ拡張コードは、その使用からではなくマクロの定義から正しいソースの場所を持ちます(フォームが実際には存在しない場合)。 DMITRY-VKが言及されているように、いくつかの方式およびLISP実装は、サブフォームの識別情報を使用してこれまでに限られたものを実装します。
Lispマクロについて知りません(私がおそらくCマクロとはかなり異なっている)、またはデバッグは、おそらく最も多くのC / C ++デバッガは、特によくCプリプロセッサマクロのソースレベルのデバッグを処理しません。
一般に、C / C ++デバッガは、マクロ定義に「ステップ」しない。マクロが複数のステートメントに展開されている場合、デバッガは通常、デバッガのステップ '操作ごとに同じソース行(マクロが呼び出される場所)にちょうど留まります。
これは、そうでなければそれらをC / C ++で避けるためのもう1つの理由よりも少し痛いマクロをデバッグマクロにすることができます。マクロが本当に不思議な方法で誤っている場合は、アセンブリモードに入り、それをデバッグするか、マクロを展開するか、マクロを展開します(手動またはコンパイラスイッチを使用して)。あなたがその極端に行かなければならないことはかなり稀です。あなたがそれが複雑であるマクロを書いているなら、あなたはおそらく間違ったアプローチを取っています。
通常、Cソースレベルのデバッグには、ライン粒度( "次の"コマンド)または命令レベルの粒度があります(「ステップイン」)。マクロプロセッサは、コンパイラがCPU命令のコンパイル済みシーケンスをソースコードラインにマッピングできるようにする処理元に特別な指令を挿入します。
Lispでは、コンパイルされたコードマッピングへのソースコードを追跡するためのマクロとコンパイラの間の規則はありませんので、ソースコードでシングルステッピングすることは必ずしも可能ではありません。
明らかなオプションは、マクロ展開コードでシングルステッピングすることです。コンパイラはすでに最終的な、拡張された、バージョンのコードを見て、マシンコードマッピングにソースコードを追跡できます。
その他のオプションは、操作中のLisp式がIDを持つという事実を使用することです。マクロが単純で、コードをテンプレートに破壊して貼り付ける場合は、ソースコードから読み出された式に、拡張コードのいくつかの表現は(EQ比較に関して)同一です。この場合、コンパイラは展開されたコードからソースコードにいくつかの式をマッピングできます。
簡単な答えは、複雑であるということです.-)プログラムをデバッグできるように貢献するいくつかの異なるものがあり、マクロを追跡するためにさらに多くのものがあります。
CとC ++では、プリプロセッサはマクロを拡張し、実際のソースコードに含まれています。発信元ファイル名と行番号は、#LINEディレクティブを使用してこの拡張されたソースファイルで追跡されます。
http://msdn.microsoft.com/ EN-US / LIBRARY / B5W2CZAY(VS.80).aspx
CまたはC ++プログラムがデバッグを有効にしてコンパイルされると、アセンブラはソース行、シンボル名、型記述子などを追跡するオブジェクトファイルに追加情報を生成します。
http://ousours.redhat.com/gdb/onlinedocs/stabs.html.
オペレーティングシステムには、デバッガがプロセスに接続してプロセス実行を制御することが可能になる機能があります。一時停止、シングルステッピングなど。
デバッガがプログラムに接続されている場合、デバッグ情報のプログラムアドレスの意味を調べて、プロセススタックとプログラムのカウンタをシンボリック形式に戻します。
動的言語は通常、インタプリタであるかバイオードVMかどうかにかかわらず、仮想マシンで実行されます。デバッガがプログラムフローを制御し、プログラム状態を検査できるようにするためのフックを提供するVMです。