15

マクロの定義が約 50 行になり、「if else」ステートメントがたくさんあります。このマクロ def'n は .h ファイルに表示されます。「TUI モードで gdb」を実行していますが、実行がそのマクロに達すると、コード ウィンドウが空白になり、マクロ コードが実行された後でのみ元に戻ります。完全なマクロ コードの行ごとの実行を確認したい。その方法を教えてください (1 つの方法は、マクロをコード内の定義に置き換えてから再コンパイルすることです。私のコードにはそのようなマクロがいくつかあるため、このオプションは使用したくありません)。

どんな助けでも大歓迎です。この問題の解決策が得られることを楽しみにしています。前処理されたファイルを使用する以外に、この問題を解決する方法があれば教えてください。数百の .c & .h ファイルに実行されるコードがあります。

4

3 に答える 3

16

1 つのオプションは、C ファイルを完全に前処理し、その中のすべてのマクロを展開してから、前処理された結果のファイルをコンパイルすることです。

たとえば、次の単純な C プログラムについて考えてみましょう。

// file: prep.c
#include <stdio.h>

#define MY_BIG_MACRO \
  int i; \
  printf("integers from 0 to 9:\n"); \
  for (i = 0; i < 10; i++) \
    printf("%d ", i); \
  printf("\n");

int main(void)
{
  MY_BIG_MACRO
  return 0;
}

コンパイルして、一時ファイル (前処理されたソース コードを含む) を保存します。

gcc -Wall -O2 -g -std=c99 prep.c -o prep.exe -save-temps

これにより、前処理されたバージョンのprep.c, prep.i(簡潔にするために短縮されています)が得られます。

# 1 "prep.c"
# 1 "C:\\MinGW\\msys\\1.0\\home\\Alex//"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "prep.c"

# 1 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.6.2/../../../../include/stdio.h" 1 3

...

int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vswscanf (const wchar_t * __restrict__,
         const wchar_t * __restrict__, __gnuc_va_list);
# 3 "prep.c" 2
# 11 "prep.c"
int main(void)
{
  int i; printf("integers from 0 to 9:\n"); for (i = 0; i < 10; i++) printf("%d ", i); printf("\n");
  return 0;
}

ここで、# 行を削除します。いずれにせよ、それらが残っていると、デバッグ情報に影響します。驚いたことに、これは、マクロが で展開されて表示されないことを意味しgdbます。

ありがたいことに、grep助けてくれます(私はgrepのプロではないので、パラメーターが正しいかどうかを確認してください。ただし、MinGW x86を搭載したWindowsで機能するようです):

grep ^[^\#].*$ prep.i > prepi.c

prep.iこれにより、 inの削除されたバージョンが得られますprepi.c

typedef unsigned int size_t;
typedef short unsigned int wchar_t;
typedef short unsigned int wint_t;

...

int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vswscanf (const wchar_t * __restrict__,
         const wchar_t * __restrict__, __gnuc_va_list);
int main(void)
{
  int i; printf("integers from 0 to 9:\n"); for (i = 0; i < 10; i++) printf("%d ", i); printf("\n");
  return 0;
}

これでコンパイルできます:

gcc -Wall -O2 -g -std=c99 prepi.c -o prepi.exe

そしてそれを実行しgdbます:

gdb prepi.exe

次のコマンドを発行します。

b main
r
l

これにより、アプリが実行main()され、到達したブレークポイントに関連するソース コードが一覧表示されます。

(gdb) b main
Breakpoint 1 at 0x40643f: file prepi.c, line 184.
(gdb) r
Starting program: C:\MinGW\msys\1.0\home\Alex\prepi.exe
[New Thread 7340.0x20c4]

Breakpoint 1, main () at prepi.c:184
184       int i; printf("integers from 0 to 9:\n"); for (i = 0; i < 10; i++) pri
ntf("%d ", i); printf("\n");
(gdb) l
179              const wchar_t * __restrict__, __gnuc_va_list);
180     int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vswscanf (c
onst wchar_t * __restrict__,
181              const wchar_t * __restrict__, __gnuc_va_list);
182     int main(void)
183     {
184       int i; printf("integers from 0 to 9:\n"); for (i = 0; i < 10; i++) pri
ntf("%d ", i); printf("\n");
185       return 0;
186     }
(gdb)

ご覧のとおり、マクロ本体がプレーン ビューになりました。

ここでの小さな問題の 1 つは、複数行のマクロ ( で続くマクロ\) が 1 行に展開されることです。それらを複数の行に展開するオプションは見つかりませんでしたが、手動で行うことができます。

于 2012-10-02T08:07:47.253 に答える
9

「人は単にstepマクロに夢中になるわけではありません。」

まだいくつかのオプションがあります。

  1. @WhozCraigが推奨するように、プリプロセッサを使用してください。
  2. コードの膨張を少し減らすには、マクロを関数に変換して再コンパイルします。
  3. 絶対に再コンパイルしたくなく、アセンブリ コードに慣れている場合はstepi、マクロを一度に 1 つの機械命令で実行するために使用できます。
于 2012-10-02T07:35:01.390 に答える
1

上記のすべてが機能しない場合はprintf/fprintf、大きなマクロ内での使用に戻る必要があります。

ライブラリの奥深くに埋もれている 300 行のマクロを処理する必要がありました。これは、手動でコンパイルして後処理されたファイルを処理するよりも簡単でした。

于 2014-02-27T09:30:59.943 に答える