【问题标题】:Simple C inline linker error简单的 C 内联链接器错误
【发布时间】:2013-05-20 09:10:34
【问题描述】:

简单的问题:

给定以下程序:

#include <stdio.h>

inline void addEmUp(int a, int b, int * result)
{
    if (result) {
        *result = a+b;
    }
}

int main(int argc, const char * argv[])
{
    int i;
    addEmUp(1, 2, &i);

    return 0;
}

我收到链接器错误...

Undefined symbols for architecture x86_64:
  _addEmUp", referenced from:
      _main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

好像不用编译。

它不应该是static,我不认为,根据我读过的内容:
Linker error inline function(因为这是在不同的对象中,并且处理2个定义而不是零)

这是一个相关链接,但它是 c++,我认为在 std C 中将代码放在标头中并不是一个好习惯:
inline function linker error

编译器信息:

cc --version
Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.3.0
Thread model: posix

编译示例:

# cc main.c 
Undefined symbols for architecture x86_64:
  "_addEmUp", referenced from:
      _main in main-sq3kr4.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocatio

【问题讨论】:

  • 你是用哪个命令编译的?
  • 你用的是什么编译器?
  • 它在 xcode 4.6.2 中发出叮当声

标签: c inline linker-errors


【解决方案1】:

尝试在编译器命令中添加“-O”选项。仅当启用优化时才启用内联。

【讨论】:

  • 确实可以消除链接器错误,但如果它不能内联,它不应该只是忽略关键字......因为它只是一个提示
  • 这就是 GCC 所做的。 Clang 尝试遵守 C99,它的解释似乎略有不同,这就是您遇到此问题的原因。 clang.llvm.org/compatibility.html#inline
【解决方案2】:

第 6.7.4 节第 7 段说:

任何具有内部链接的函数都可以是内联函数。对于具有外部链接的函数,适用以下限制: 如果函数使用inline 函数说明符声明,则它也应在同一翻译单元中定义。如果翻译单元中函数的所有文件范围声明都包含inline 函数说明符而没有extern,则该翻译单元中的定义是内联定义内联定义不提供函数的外部定义,并且不禁止在另一个翻译单元中进行外部定义。内联定义提供了外部定义的替代方案,翻译器可以使用它来实现对同一翻译单元中函数的任何调用。 未指定对函数的调用是使用内联定义还是外部定义

您的文件不包含addEmUp 的外部定义,编译器选择在main 的调用中使用外部定义。

提供外部定义,或将其声明为static inline

【讨论】:

  • 静态内联不起作用(至少在实际项目中不起作用;没有尝试示例一)...我找到了一个有效的 Objective-C 特定宏,我正在更新.
  • static inline 应该工作,不过。你能把它归结为链接器错误仍然存​​在,但代码对于 SO 来说足够小吗?
  • 如果只在一个文件中使用,它应该也可以在实际项目中工作。好吧,您始终可以选择提供外部定义以供回退。
  • 这里是详细说明差异的 clang 参考:clang.llvm.org/compatibility.html#inline
【解决方案3】:

由于 6.9/5,该程序会导致未定义的行为(无需诊断),有时非正式地称为“单一定义规则”:

如果用外部链接声明的标识符在表达式中使用(而不是作为 sizeof 或 _Alignof 运算符的操作数的一部分,其结果是整数常量),则在整个程序的某处应该恰好有一个外部定义标识符;否则,不得超过一个。

您的程序使用标识符addEmUp,但没有为其提供外部定义。 (如前所述,“内联定义不为函数提供外部定义”)。

我们不需要开始讨论函数调用调用的定义等等等等。未定义 ODR 违规且无需诊断的原因是为了让编译器编写者更容易;如果此代码需要诊断,那么编译器将不得不通过禁用内联优化来检查外部定义是否存在,这确实是浪费时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-31
    • 1970-01-01
    • 1970-01-01
    • 2012-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多