15

我有一个宏,它的定义大约有 50 行,并且有很多“if else”语句。此宏 def'n 出现在 .h 文件中。我正在运行“TUI 模式下的 gdb”,但是当执行到达该宏时,代码窗口变为空白,并且仅在宏代码执行后才返回。我想逐行查看完整宏代码的执行情况。请让我知道如何做到这一点(一种方法是用代码中的定义替换宏,然后重新编译它。我不想使用这个选项,因为我的代码中有几个这样的宏)。

任何帮助将不胜感激。期待得到这个问题的解决方案。请让我知道这个问题是否有其他方法而不是使用预处理文件?我的代码可以运行到数百个 .c 和 .h 文件中。

4

3 回答 3

16

一种选择是完全预处理您的 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;
}

现在你想摆脱#-lines。一种或另一种方式,如果它们被留下,它们将影响调试信息。令人惊讶的是,这意味着宏不会在gdb.

值得庆幸的是,grep可以提供帮助(我不是 grep 专业人士,因此请检查参数是否正确,但它们似乎适用于使用 MinGW x86 的 Windows):

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

这将为您提供prep.iin的剥离版本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)

如您所见,宏主体现在处于普通视图中。

这里的一个小问题是多行宏(以 继续\)被扩展为单行。我还没有找到将它们扩展为多行的选项,但您可以手动执行此操作。

于 2012-10-02T08:07:47.253 回答
9

“一个不简​​单的step变成宏”。

你还有几个选择:

  1. 正如@WhozCraig 推荐的那样,使用预处理器。
  2. 为了减少代码膨胀,将宏转换为函数并重新编译。
  3. 如果您绝对不想重新编译并且您对汇编代码感到满意,则可以使用stepi一次执行一条机器指令来执行宏。
于 2012-10-02T07:35:01.390 回答
1

如果以上所有方法都不起作用,那么你真的应该回到printf/fprintf在你的大宏中使用。

我不得不处理一个 300 行的 MACRO,深埋在库中。这比手工编译和处理后处理文件更容易。

于 2014-02-27T09:30:59.943 回答