【问题标题】:Strange symbol name in output of nm commandnm 命令输出中的奇怪符号名称
【发布时间】:2011-05-17 19:28:39
【问题描述】:

我构建了一个名为 InterfaceLayer.so 的动态库。 当我打电话时:

> nm InterfaceLayer

作为输出,我得到一些看起来像这样的符号:

00000e28  T _Z5startv

虽然我期望它是“start”,就像我在代码中定义的函数的名称一样。

为什么会这样?

【问题讨论】:

    标签: c linux linker nm


    【解决方案1】:

    这是因为 C++ 名称修改

    nm -C
    

    对它们进行解码。

    为了防止名称混淆,

    • 使用 C 编译器(gcc,而不是 g++),将源文件命名为 .c(而不是 .cpp)
    • 或声明 extern "C":

    .

    我的.h

      extern "C" 
      {
            void start();
            void finish();
      }
    

    这将为它们提供“C”链接,这意味着它们不能被重载,不能通过引用传递,没有 c++ :)

    【讨论】:

    • extern "C" 不代表函数不能通过引用传递。
    • 建议从 C++ 切换到 C“以防止名称混乱”听起来像是使用断头台来防止头皮屑的建议。顺便说一句,OP 从来没有说过他们想阻止它。
    • 同意。解释 C++ 是重整的来源仍然可能会增加视角。 “为什么会发生这种情况”是明确的问题。
    【解决方案2】:

    听起来像C++ name mangling

    【讨论】:

    • 我经常使用 c++filt 来对它们进行分解:c++filt _Z5startv
    • nm myApp | c++过滤; # 正是我需要的。我在 OSX 和 XCode 上使用它扭曲的 GNU 工具堆栈,它不支持 nm -C。谢谢@karlphillip
    【解决方案3】:

    正如其他答案所提到的,这可能是因为 C++ 名称修改。如果您希望符号可以通过它的“未损坏”名称访问,并且它是在 C++ 中实现的,您需要向我们extern "C" 告诉 C++ 编译器它具有 C 链接。

    在具有函数原型的标头中,您需要类似以下内容:

    #if defined(__cplusplus)
    extern "C" {
    #endif
    
    // the prototype for start()...
    
    
    #if defined(__cplusplus)
    }
    #endif
    

    这将确保如果函数被 C++ 编译器使用,它会在声明中获得 extern "C",并且如果它被 C 模块使用,它不会被 extern "C" 混淆说明符。

    如果您在函数定义之前包含标头,则 .cpp 文件中的实现不需要这些东西。它将使用从先前声明中看到的链接规范。但是,我还是更喜欢用extern "C" 来装饰函数定义,以确保一切都同步(请注意,在 .cpp 文件中,您不需要 #ifdef 预处理内容 - 它总是被编译为 C++ .

    【讨论】:

      猜你喜欢
      • 2017-06-09
      • 1970-01-01
      • 2020-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-21
      相关资源
      最近更新 更多