Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用gdb调试C预处理器宏中的崩溃_C_Macros_Gdb_C Preprocessor - Fatal编程技术网

使用gdb调试C预处理器宏中的崩溃

使用gdb调试C预处理器宏中的崩溃,c,macros,gdb,c-preprocessor,C,Macros,Gdb,C Preprocessor,我有一个带有多行宏的C程序,该程序在宏中崩溃,我如何确定宏中崩溃发生的位置 这是我的程序的简化版本。实际上,崩溃是多行的,不容易手动扩展 #include <stdio.h> #include <stdarg.h> #define CRASHES(ptr) \ (*(ptr) == 123) main() { char *foo = NULL; if (CRASHES(foo)) printf("This will never ha

我有一个带有多行宏的C程序,该程序在宏中崩溃,我如何确定宏中崩溃发生的位置

这是我的程序的简化版本。实际上,
崩溃
是多行的,不容易手动扩展

#include <stdio.h>
#include <stdarg.h>
#define CRASHES(ptr) \
    (*(ptr) == 123)
main()
{
    char *foo = NULL;
    if (CRASHES(foo))
        printf("This will never happen.");
}
#包括
#包括
#定义崩溃(ptr)\
(*(ptr)==123)
main()
{
char*foo=NULL;
如果(崩溃(foo))
printf(“这永远不会发生”);
}
当使用
gdb a.out
编译和运行此程序时,我得到了预期的
EXC\u BAD\u访问权限(我使用的是带有gdb 6.3的Mac OS X),但是崩溃指向第8行,而不是第4行,而实际上是导致崩溃的


我已经按照建议使用附加调试标志
-gdwarf-2
-g3
编译了该程序,并在宏本身中插入了几个
assert()
s。遗憾的是,这并没有提供更多信息。

关于宏调试的许多有价值的信息


…另一种方法是使用预处理器,即使用
-e
编译它,并将扩展的宏复制粘贴到您的src代码中,然后查看是否可以从此处进行调试。

i是否可以将其转换为实际函数?这是宏的最大弊端之一。

你没有说它是如何崩溃的。如果是segfault,请注意,它可能会在实际取消引用错误指针值的时间稍晚发生。

当然,这会崩溃,因为您正在延迟空指针…(这不是正确的问题吗?)。有了这个特殊的例子,就很容易了:gcc-g2,gdb说

Program received signal SIGSEGV, Segmentation fault.
0x080483d9 in main () at crash.c:10
10      if (CRASHES(foo))

这一点相当清楚,您可以自己展开宏并查看原因(因为*foo==123访问您无法读取的内存,因为foo为NULL)。在更复杂的情况下,gcc-E有助于避免使用宏。

这个链接看起来不错。在过去,我用编译器args扩展了宏文本,然后编译并调试了该文件。查看(g)cc的-E选项。不幸的是,
info宏…
等。生成
GDB没有该代码的预处理器宏信息,即使使用命名标志编译也是如此。但是用-E编译并粘贴回来就做到了,我只希望GDB能帮我做到这一点。:)有时很难将某些内容转换为函数调用(例如,此处-它是作为宏进行的,以获得性能,而不是重复各种类型的代码),不幸的是,这并不容易。第一个宏将引用局部变量的另一个宏展开多次。编辑:它实际上非常类似于osgx引用的代码。很公平。尽管宏的性能参数已经过时。大多数现代编译器都足够智能,可以自动内联小到可以定义为宏的函数。需要访问局部变量是一个很好的论据,这就是为什么我喜欢使用匿名和/或嵌套函数的新语言。也许有一天我们会在c/c++中看到这一点。哈哈,jk。为什么应该是四号线?崩溃发生在第8行,在那里宏被展开并使用。宏本质上不会导致segfault,这是因为foo的值,在这种情况下,因此崩溃发生在第8行是正确的。如果它指向4,那就是误导。