使用llvm和lldb处理OSX,我有以下代码:
#include <stdio.h>
class A{
public:
void f() __attribute__((noinline))
{
printf("f()\n");
}
void g() __attribute__((noinline))
{
printf("g()\n");
}
};
int main()
{
A a;
a.g();
return 0;
}
在main()中断,并尝试从调试器调用p a.f()
时,我得到:
但是,错误:无法查找符号:__ ZN1A1fEv
调用p g.f()
效果很好。
我知道f()可能会被优化掉,但有没有办法禁用这种优化,所以我可以在调试器中使用它?
谢谢!
答案 0 :(得分:2)
虽然在某些情况下将定义移出线可能会有所帮助,但在所有情况下都无济于事,例如:如果它不是odr c ++成员函数,而只是一个静态函数,或者整个程序是LTO优化的,并且该函数不在本地翻译单元之外引用。
在这些情况下(也可能是这一个),您应该将函数标记为__attribute__((used))
,以告诉编译器该函数已被使用,并确保并在生成的对象文件中为其生成代码 - 这也意味着也会生成调试信息。
您的最终代码最终将如下所示:
#include <stdio.h>
class A {
public:
void f() __attribute__((noinline, used))
{
printf("f()\n");
}
void g() __attribute__((noinline))
{
printf("g()\n");
}
};
int main()
{
A a;
a.g();
return 0;
}
这是设计__attribute__((used))
的原因之一。来自gcc documentation:
此属性附加到函数,意味着即使看起来函数未被引用,也必须为函数发出代码。例如,仅在内联汇编中引用该函数时,这很有用。 当应用于C ++类模板的成员函数时,该属性还意味着如果实例化类本身,则实例化该函数。
这意味着即使没有使用,也可以保证在所有情况下都能发出该功能。
(作为进一步的补充,我还没有证实这实际上可以用于LTO优化 - 它可能应该,但我认为这是一个通常不会想到的角落情况,我直到现在才这样做我在LTO工作:)
答案 1 :(得分:1)
将f
的定义移到课堂外:
#include <stdio.h>
class A {
public:
void f();
void g() __attribute__((noinline))
{
printf("g()\n");
}
};
void A::f()
{
printf("f()\n");
}
int main()
{
A a;
a.g();
return 0;
}
在Linux上使用gcc 4.8.4,$ g++ t.cc
和$ g++ -g t.cc
对我有用。它也可以与您的工具链一起使用。
$ g++ t.cc
$ nm a.out | grep _ZN1A
000000000040052e T _ZN1A1fEv
0000000000400562 W _ZN1A1gEv
作为替代方案,如echristo的回答所述,将used
添加到f
的属性中,并将其保留在类中。这也适用于$ g ++ t.cc and
$ g ++ -g t.cc`:
$ g++ -g t.cc
0000000000400548 W _ZN1A1fEv
0000000000400560 W _ZN1A1gEv
添加used
也适用于g++ -O2 -g t.cc
。