我刚刚阅读了GCC函数属性artificial
,但没有完全得到描述。你能给我一些有用的例子吗?
答案 0 :(得分:12)
另一个答案没错,但也许我可以更好地解释一下。
想象一下foo.c
中的这个函数,行号:
10: static inline int foo(struct q *x)
11: {
12: return bar(x + 1);
13: }
这是从另一个函数调用两次:
20: void baz(void)
21: {
22: x = foo(qa);
23: x = foo(qb);
24: }
不幸的是,bar()
崩溃了。这是回溯:
#0 0x00000000004b1a2a in bar (x=0x8) at foo.c:5
#1 0x0000000000416ee0 in baz () at foo.c:12
#2 0x0000000000413fab in main () at foo.c:30
由于foo
是内联的,因此它不属于回溯,但等待foo.c:12
位于foo
,而低于它main
。没有什么可以告诉我们baz
中的哪一行导致了崩溃。
如果我们将foo标记为人为的,我们反而得到这个回溯:
#0 0x00000000004b1a2a in bar (x=0x8) at foo.c:5
#1 0x0000000000416ee0 in baz () at foo.c:22
#2 0x0000000000413fab in main () at foo.c:30
它不再指向foo
。相反,它向我们显示了从foo
调用foo.c:22
的位置。非常容易说出qa
是有问题的变量。
答案 1 :(得分:4)
来自gcc文档,
此属性对于小型内联包装器非常有用,如果可能,应在调试期间将其作为一个单元出现。根据调试信息格式,它或者意味着将函数标记为人工,或者使用内联体内所有指令的调用者位置。
在Inline is as fast as a Macro中,extern inline
函数的末尾有一个特殊注释。我们的想法是,如果您有一个带有extern inline
的标头,则可以使用 artificial 属性,调试信息将使用inline
所使用的位置。即,extern inline
被调用,内联。
与说明中一样,人工仅用于内联,它控制调试器处理此代码的方式。它对生成的代码或其他任何内容都没有影响。
答案 2 :(得分:1)
GCC开发人员Ian Lance Taylor在__gnu_inline__
and __artificial__
表示:
我承认人工属性的文档不是很好。在一个 函数,它基本上意味着如果函数是内联的,那么 调试器不会单步执行内联指令。
你能给我一些有用的例子吗?
我至少可以提供一个额外的一个:带有内联汇编单行代码的步进代码。很多时候,你需要下一个C语句,而不是下一个汇编语句。