0

シンプルで迅速な一般的なコンソール デバッガーのようなことをしたいと考えています。この小さなライブラリは、メイン プログラムに組み込む必要があります。

したがって、コンソールモードでプログラムを実行しているときに、次のようなことをしたいと思います:

"input: print i" "output: 15.53" "input: set color 255" "input: print color" "output: 255"

また、「i」と「color」の両方が、コード内で事前に宣言された変数になります。これはインタープリターではなく、変数の内容を確認および変更するための便利な方法です。

GDB は、私がコーディングするコンピューター グラフィックス プログラムにこのコードを使用するため、私の問題に対する有効な解決策ではありません。そのため、「リリース モード」で実行できる必要があります。

これまでに見つけた非常に単純な解決策の 1 つは、void ポインター、ポインターのデータ型、および変数名を表す文字列を含む構造体のリストを作成することです。しかし、それは私が想像するほど自動的ではありません。

C++ で color という名前の整数変数のアドレスを取得するために、文字列 (たとえば "color") を変換する方法はありますか? そうでない場合、どうすれば問題を解決できますか?

4

11 に答える 11

4

あなたはこのイディオムを知らないかもしれませんが、これを実装するのが簡単になるかもしれません:

#include <stdio.h>
#define REPORT(V) printf("%s: %i\n", #V, V);
int main() {
  int i = 5;
  REPORT(i);
  return 0;
}

出力は

i: 5
于 2009-10-29T18:23:06.997 に答える
4

心のフェイントではありませんが、 and を使用dlopendlsymて、グローバルに宣言された変数のアドレスを取得できます。

于 2009-10-29T18:24:25.637 に答える
3

変数名はプログラマ向けであり、C++ はメタデータを保存しません。(ソースコードに関するデータ)。実行時に名前で変数にアクセスすることはできません。

つまり、std::mapまたは unordered_map ( tr1またはboostのいずれか) などを使用して、キーと値を取得できます。問題は、コンテナー内で値が均一でなければならないことです。これはBoost.Anyを使用することで軽減できます。

于 2009-10-29T18:14:44.057 に答える
2

いいえ、できません。ソース コードをバイナリ形式にコンパイルし、シンボルを取り除くと、人間が判読できる名前の記録がバイナリにありません。

C++ の 1 つのオプションは、std::string から変数のデータ型への std::map を使用することです。その後、 を参照できますmy_map["my_variable_name"] = new_value。ただし、これにはパフォーマンスへの影響が少なくないため、ほとんどの場合は良い考えではありません。

于 2009-10-29T18:15:21.700 に答える
1

外部シンボル ファイル (コマンド)で GDB を使用できます。symbol-fileそのため、外部ファイルのデバッグ情報を使用して実行可能ファイルをビルドする場合、独自のデバッガーを作成する必要さえありません...顧客がインストールした実行可能ファイルをデバッグするときは、シンボル ファイルを持参することを忘れないでください。

于 2009-10-29T20:37:55.023 に答える
1

私の知る限り、これに対する一般的な解決策はありません。これを行うには、コンパイラによって生成されたデバッグ情報を使用できます。明らかに、リリース ビルドにもデバッグ情報を含める必要があります。また、特定のプラットフォーム/コンパイラ用のこれらのデバッグ情報の形式を理解し、読み取り、解析する必要があります...

あなたが言及した方法(「デバッガー」からアクセスしたい場所を明示的に宣言する)が、ここに行く最良の方法のようです。負担をいくらか軽減するために、マクロをシンタックス シュガーとして使用できます。

struct descriptor {
    const char* name;
    const char* type;
};

#define DEFGLOBAL(type, name) \
    static struct descriptor name ## _descriptor = { \
         # name, # type \
    }; \
    type name

DEFGLOBAL(int, some_number);

Emacs のソース コードを確認することをお勧めします。上記の行に沿って何かを行い、C 変数を Lisp インタープリターにエクスポートします。また、プリミティブ関数などを Lisp レベルにエクスポートするためにも使用します。

于 2009-10-29T18:19:49.240 に答える
0

あなたが考えた単純な解決策は、基本的に非デバッグ C/C++ コードで利用できる唯一の解決策です。ただし、考慮すべき 2 つの障害があると思います。

  1. グローバル変数のみを観察できます。おそらくトップレベルの処理ループの一部として、コマンドラインからの入力を処理するときにこれらのスタックフレームが存在しないため、関数内のローカル変数はインスペクターで使用できません。(すべての関数でコマンドライン入力を処理しない限り、これはお勧めしません。その場合、コマンドを入力したときにどの関数のスタックフレームが検査されるかわかりません。)
  2. コンパイラが特定のレジスタの最適化を行うのを防ぎます。コードが変数のアドレスを取得する場合 (たとえば、その変数へのポインターをインスペクターのシンボル テーブルに含めるため)、コンパイラーは、そうでなければその変数をレジスターのみに保持する場合でも、その変数をメモリー位置に配置する必要があります。スピードのために。
于 2009-10-29T18:35:13.157 に答える
0

がんばるか、Luaを使ってください。リンク:

于 2009-10-29T18:21:10.993 に答える
0

それを最適化し、デバッグシンボル(GCCで可能)を使用してビルドし、デバッグシンボルの読み取り方法などを理解して、gdbと同じようにデバッグすることができます..しかし、それは本当にやり過ぎのようです..実行可能なデザインであり、適切な言語を使用してそのようなことを行うことはありますか? このコンソール デバッガーが使用されるのはいつですか?

于 2009-10-29T18:22:44.943 に答える
0

GDB を「リリース モード」で実行できないと考える理由は何ですか? 変数を識別するために GDB が依存するのはデバッグ シンボルであり、他のコンパイラ フラグが指定されているかどうかに関係なくビルドできます。最適化と「リリース モード」を構成するその他すべてを有効にでき、GDB が使用するデバッグ シンボルを生成できます。

于 2009-10-30T12:22:31.453 に答える
0

Lua の代わりに Boost::Python; を使用することもできます。また、クイック アンド ダーティ スクリプト API を作成することもできます。

于 2009-10-30T10:24:19.883 に答える