すべてのフィールドとそのアドレス、および対応する値を表示する構造体へのポインターに対して、gdbのような出力を作成する方法が必要です。メンバーごとに印刷する代わりに、これを行うためのクリーンな方法はありますか?pstructやlibgdbのような他の外部ツールは使用できません。Cプログラムの中からやりたいです。システムにgdbがあり、使用できます。御時間ありがとうございます。
5 に答える
オプションは次のとおりです。
a)バイナリからデバッグシンボルを読み取り、GDBが構造体メンバーを判別するのと同じ方法でそれらを解釈し、その情報を一般化された印刷ルーチンに渡します。
b)手動またはカスタムビルドステージを使用して、構造に関するメタデータをCプログラムにコンパイルします。
c)メンバーごとにメンバーを印刷します。
あなたはそれをするための関数を書くことができますか?
void printStructPtr( struct name *p)
{
printf("{ ");
//print all members one by one separated by commas
printf("...", p->member1);
printf("...", p->member2);
printf("}");
}
ジェネリックにしたい場合は、voidポインターを受け取り、適切にキャストします。
おそらく、GCCコンパイラをカスタマイズして(たとえば、MELTドメイン固有言語を使用してGCCを拡張する)__attribute__
、タイプ(おそらく注釈付き)から印刷コードを生成する新しいものを追加することができます。しかし、そのようなアプローチには数日かかるので、本当に大きなプログラムがない限り、一般的にはお勧めしません。
問題は最初に考えているよりも複雑であることに注意してください。a内のポインタをstruct
印刷して追跡する必要がある場合があります(または、ハウスキーピング専用の場合は省略してください)。また、複雑なデータ構造には共有コンポーネントがあるため、すでにアクセスしたデータのセットを管理する必要があります。また、いくつかの識別子(およびC宣言union
の外にあるそれに関する規則)がない限り、-sを出力することは一般に不可能であることに注意してください。
私はむしろ、データ構造の記述(追加の注釈付き)とその出力印刷ルーチン、およびデータのC宣言を受け入れるツールを使用(または開発)したいと思います。
ところで、あなたの問題はシリアル化に関連しています
すべての構造体メンバーが同じである場合は、最初のメンバーへのポインターをインクリメントして、構造体の他のメンバーにアクセスできますが、構造体にパディングが行われることがあるため、これは一般的にはお勧めできません。例えば:
struct my_struct{
int a;
int b;
int c;
};
struct my_struct t = {1, 2, 3};
int *p = &t.a;
for (i=0; i<sizeof(t)/sizeof(int); i++, p++) {
printf("%d\n", *p);
}