【问题标题】:C++ - Calling unused function from debuggerC++ - 从调试器调用未使用的函数
【发布时间】:2016-10-31 17:08:45
【问题描述】:

使用 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() 可能会被优化掉,但是有什么方法可以禁用这种优化,所以我可以在调试器中使用它吗?

谢谢!

【问题讨论】:

  • 尝试在某处添加符号,例如,main() 中的f;(不是f();)。
  • 检查您的编译器命令行优化开关或 IDE 编译器设置。几乎所有现有的编译器都允许禁用优化。
  • 作为一个快速hack,你可以尝试制作virtual的方法。
  • @lorro - 你能解释一下语法吗?
  • @maxik 非虚成员函数不会影响对象的大小

标签: c++ llvm lldb


【解决方案1】:

虽然在某些情况下移动定义可能会有所帮助,但并非在所有情况下都有帮助,例如如果它不是一个 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 上工作 :)

【讨论】:

  • 太好了,我已经用这个选项扩展了我的答案。
  • 我真的会避免使用外线定义来尝试解决此类问题。它将对程序产生更广泛的影响,并且仍然可以被 LTO 或任何其他跨模块类型的优化打破。这个用例是创建 __attribute__((used)) 的原因之一。我会更新我的答案来解释一下。
【解决方案2】:

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;
}

这对我在使用 gcc 4.8.4 的 Linux 上的 $ 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.ccand$ g++ -g t.cc`:

$ g++ -g t.cc
0000000000400548 W _ZN1A1fEv
0000000000400560 W _ZN1A1gEv

添加used 也适用于g++ -O2 -g t.cc

【讨论】:

    猜你喜欢
    • 2015-10-31
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 2016-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-01
    相关资源
    最近更新 更多