C 如何使用gdb查看宏展开的每一行的逐步执行

C 如何使用gdb查看宏展开的每一行的逐步执行,c,linux,gdb,C,Linux,Gdb,我有一个宏,它的定义大约有50行,有很多“if-else”语句。此宏定义显示在.h文件中。我正在运行“gdb in TUI模式”,但当执行到达该宏时,代码窗口变为空白,仅在宏代码执行后返回。我希望看到完整宏代码的逐行执行。请告诉我怎么做(一种方法是用代码中的宏定义替换宏,然后重新编译它。我不想使用此选项,因为我的代码中有几个这样的宏) 任何帮助都将不胜感激。期待着找到解决这个问题的办法。请让我知道是否有其他方法解决这个问题,而不是使用预处理文件?我有一个代码,它可以运行到几百个.c和.h文件中。

我有一个宏,它的定义大约有50行,有很多“if-else”语句。此宏定义显示在.h文件中。我正在运行“gdb in TUI模式”,但当执行到达该宏时,代码窗口变为空白,仅在宏代码执行后返回。我希望看到完整宏代码的逐行执行。请告诉我怎么做(一种方法是用代码中的宏定义替换宏,然后重新编译它。我不想使用此选项,因为我的代码中有几个这样的宏)

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

“我们不需要简单地将
步进宏。”

您仍然有一些选择:

  • 按照@WhozCraig的建议使用预处理器
  • 为了减少代码膨胀,请将宏转换为函数并重新编译
  • 如果您绝对不想重新编译,并且对汇编代码感到满意,则可以使用
    stepi
    一次执行一条机器指令来执行宏

  • 一种方法是完全预处理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;
    }
    
    这将为您提供一个预处理版本的
    prep.c
    prep.i
    (为简洁起见缩短):

    这将为您提供
    prepi.c
    中的
    prep.i
    的精简版本:

    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;
    }
    
    并在
    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)
    
    (gdb)b main
    0x40643f处的断点1:文件prepi.c,第184行。
    (gdb)r
    启动程序:C:\MinGW\msys\1.0\home\Alex\prepi.exe
    [新螺纹7340.0x20c4]
    断点1,main()位于prepi.c:184
    184国际一级;printf(“从0到9的整数:\n”);对于(i=0;i<10;i++)pri
    ntf(“%d”,i);printf(“\n”);
    (gdb)l
    179施工图(限制表、gnuc表);
    180 int uuuu属性uuu((uu cdecl_uuu))uuu属性uuu((uuu nothrow_uu))vswscanf(c
    限制,
    181施工图(限制表、gnuc表);
    182内部干管(空)
    183     {
    184 int i;printf(“从0到9的整数:\n”);用于(i=0;i<10;i++)pri
    ntf(“%d”,i);printf(“\n”);
    185返回0;
    186     }
    (gdb)
    
    如您所见,宏主体现在位于普通视图中


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

    如果以上所有操作都不起作用,您应该在大宏中重新使用
    printf/fprintf


    我不得不处理一个300行的宏,埋在图书馆深处。这比手工编译和处理后处理文件要容易。

    在我接受自己的建议并开始大量阅读20000行预处理源代码之前,我会选择#3,但我对反汇编程序的业务端很满意。也许OP也是。你介意解释一下我的答案到底错在哪里吗?我可以从这样的解释中学到一两件事。谢谢你的时间和回答。对于这个问题,除了使用预处理文件,还有其他方法吗?我有一个代码运行到几百个.c和.h文件中。我不知道还有其他方法,尽管可能有(使用gcc/gdb或其他工具集)。抱歉,哦,哇,这是一个精心设计的、详细的、聪明的答案。无法想象为什么有人会投反对票。非常有帮助,谢谢你花时间发布。奇怪的是,GDB的宏观理解是错误的
    gcc -Wall -O2 -g -std=c99 prepi.c -o prepi.exe
    
    gdb prepi.exe
    
    b main
    r
    l
    
    (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)