gdb define查看一个宏(C预处理宏)

来源:互联网 发布:淘宝自定义分类模板 编辑:程序博客网 时间:2024/06/05 09:14

转自:http://www.eifr.com/article.php?id=1298&act=print

gdb define查看一个宏(C预处理宏)

  某些语言,例如C和C++,提供定义和引用“预处理宏”的方法,这些宏可以展开为符号串。GDB 可以计算包含宏的表达式,显示宏展开的
结果,并 且显示宏的定义,包括在何处定义的。
  可能需要特别编译程序来给GDB提供预处理宏的信息。大多数编译器在调试信息中不包括宏,即使编译时使用’-g’选项。
  程序可能在某个点定义一个宏,在后面删除这个定义,然后在此后给这个宏提供另外的定义 。因此,在程序里不同点上,同一个宏可能
有不同的定义,或者根本就没有定义。如果在当前堆栈帧上,GDB 使用这个帧源代码行范围的宏。否则,GDB 使用当前位置范围的宏
  同时,GDB 不支持##符号剪接操作符,#宏字符串常量替换操作符,或者可变长宏。
  无论何时GDB计算表达式,总会将在表达式里引用的宏展开。GDB 也提供下列命令来明确地识别宏。
macro expand expression
macro exp expression
    显示表达式里引用的所有预处理宏的展开结果。由于GDB只简单地展开宏,不会去解析结果,因此表达式不必是有效的;可以是包
    含任意符号的的字符串。
macro expand-once expression
macro exp1 expression
    (此命令尚未实现。)显示在表达式里引用的预处理宏的展开结果。表达式里的所引用的宏不会改变。这个命令可以更清楚的查
    看一个特殊宏,而不会被更多的展开所迷惑。由于GDB只是简单展开宏,而不解析结果,表达式不必是有效的;可是是任意符号的
    字符串。
info macro macro
    显示名为macro的宏的定义,并显示这个定义是在代码的何处设立的。
macro define macro replacement-list
macro define macro(arglist) replacement-list
    (此命令尚未实现。)为名为macro的宏引入一个定义,对其的引用将被给定的replacement-list所替换。此命令的第一中
    形式定义了“对象式”的宏,不带参数;第二种形式定义了一个“函数式”的宏,用给定的arglist作为参数的。
    用此命令引入的定义,其范围在GDB所计算的所有表达式中,知道用命令macro undef命令删除之,如下所述。此定义会覆盖调试程
    序里所有名为macro的宏定义,并且也包括任何用户提供的定义。
macro undef macro
    (此命令尚未实现。)删除所有用户提供的名为macro宏定义。此命令只影响用命令macro define所定义的宏。如前所述;不能删
    除调试程序里的定义宏。
macro list
    (此命令尚未实现。)列举所有用macro define命令定义的宏。
  下面的例子展示了如何使用上述命令。首先,看一下源代码:
    $ cat sample.c
    #include <stdio.h>
    #include “sample.h”
    #define M 42
    #define ADD(x) (M + x)
    main ()
    {
    #define N 28
      printf (“Hello, world!\n”);
    #undef N
      printf (“We’re so creative.\n”);
    #define N 1729
      printf (“Goodbye, world!\n”);
    }
    $ cat sample.h
    #define    Q <
    $
  现在,让我们用GNU C编译器GCC来编译此程序。我用在编译的时候指定’-gdwarf-2′和’-g3′参数来产生预处理宏的调试信息。
    $ gcc -gdwarf-2 -g3 sample.c -o sample
    $
  接着,我们就可以启动GDB来调试此例子程序了:
    $ gdb -nw sample
    GNU gdb 2002-05-06-cvs
    Copyright 2002 Free Software Foundation, Inc.
    GDB is free software, …
    (gdb)
  我们可以展开宏并检查其定义,甚至是在程序尚未运行时。GDB 使用当前代码位置来判断哪个宏的定义处于此范围之内:
    (gdb) list main
    3
    4 #define M 42
    5 #define ADD(x) (M + x)
    6
    7 main ()
    8 {
    9 #define N 28
    10 printf (“Hello, world!\n”);
    11 #undef N
    12 printf (“We’re so creative.\n”);
    (gdb) info macro ADD
    Defined at /home/jimb/gdb/macros/play/sample.c:5
    #define ADD(x) (M + x)
    (gdb) info macro Q
    Defined at /home/jimb/gdb/macros/play/sample.h:1
    included at /home/jimb/gdb/macros/play/sample.c:2
    #define Q <
    (gdb) macro expand ADD(1)
    expands to: (42 + 1)
    (gdb) macro expand-once ADD(1)
    expands to: once (M + 1)
    (gdb)
  注意,在上面的这个例子里,macro expand-once只把原文本引用的宏展开–ADD的引用–但不展开宏M,此宏由ADD所引用。
  一旦程序运行起来后,在当前堆栈帧的源代码上,GDB使用有效的宏定义:
    (gdb) break main
    Breakpoint 1 at 0×8048370: file sample.c, line 10.
    (gdb) run
    Starting program: /home/jimb/gdb/macros/play/sample
    Breakpoint 1, main () at sample.c:10
    10 printf (“Hello, world!\n”);
    (gdb)
  在第10行,宏N的有效定义是在第9行:
    (gdb) info macro N
    Defined at /home/jimb/gdb/macros/play/sample.c:9
    #define N 28
    (gdb) macro expand N Q M
    expands to: 28 < 42
    (gdb) print N Q M
    $1 = 1
    (gdb)
  如果我们单步执行到删除N的定义之后,并给其新的定义,GDB会在每个点上找到有效的定义(或者没有定义):
    (gdb) next
    Hello, world!
    12 printf (“We’re so creative.\n”);
    (gdb) info macro N
    The symbol ‘N’ has no definition as a C/C++ preprocessor macro
    at /home/jimb/gdb/macros/play/sample.c:12
    (gdb) next
    We’re so creative.
    14 printf (“Goodbye, world!\n”);
    (gdb) info macro N
    Defined at /home/jimb/gdb/macros/play/sample.c:13
    #define N 1729
    (gdb) macro expand N Q M
    expands to: 1729 < 42
    (gdb) print N Q M
    $2 = 0
    (gdb)
原创粉丝点击