简体   繁体   English

没有-O2的gcc无法内联函数

[英]gcc fails to inline functions without -O2

I've recently run into a problem with compiling a piece of code after upgrading debian testing, getting the gcc 6.2.1 compiler. 最近,在升级debian测试并获得gcc 6.2.1编译器后,我遇到了编译一段代码的问题。 I've boiled it down to this simple example: 我将其简化为以下简单示例:

inline int func(void) {
    return 0;
}

int main (int argc, char **argv) {
    func();
}

The code does not compile with the following: 该代码不能与以下内容一起编译:

gcc -o exec code.c # gcc 6.2.1

It fails with: 它失败并显示:

undefined reference to 'func'

I have also tried and failed with gcc 4.8, 4.9 and 5 on the same host. 我也在同一主机上尝试使用gcc 4.8、4.9和5失败。 It does compile if I add: 如果我添加,它将编译:

gcc -o exec code.c -O2 # gcc 6.2.1

I'm really curious as to why it works with the -O2 flag but not without, I'd expect this to work? 我真的很好奇为什么它可以与-O2标志一起使用,但并非没有,我希望这可以起作用?

Adding the "-O" option to your compiler command. 在编译器命令中添加“ -O”选项。 Inlining is turned on only when optimization is enabled. 仅在启用优化时才启用内联。

C99 inline functions C99内联功能

By default, Clang builds C code in GNU C11 mode, so it uses standard C99 semantics for the inline keyword. 默认情况下,Clang在GNU C11模式下构建C代码,因此它对inline关键字使用标准的C99语义。 These semantics are different from those in GNU C89 mode, which is the default mode in versions of GCC prior to 5.0. 这些语义与GNU C89模式中的语义不同,后者是5.0之前的GCC版本中的默认模式。 For example, consider the following code: 例如,考虑以下代码:

inline int add(int i, int j) { return i + j; }

int main() {
  int i = add(4, 5);
  return i;
}

In C99, inline means that a function's definition is provided only for inlining, and that there is another definition (without inline) somewhere else in the program. 在C99中,内联意味着仅提供用于内联的函数定义,并且程序中其他位置还有另一个定义(无内联)。 That means that this program is incomplete, because if add isn't inlined (for example, when compiling without optimization), then main will have an unresolved reference to that other definition. 这意味着该程序是不完整的,因为如果未内联add(例如,未经优化的编译时),则main将具有对该其他定义的未解决的引用。 Therefore we'll get a (correct) link-time error like this: 因此,我们将收到一个(正确的)链接时错误,如下所示:

Undefined symbols:
  "_add", referenced from:
      _main in cc-y1jXIr.o

By contrast, GNU C89 mode (used by default in older versions of GCC) is the C89 standard plus a lot of extensions. 相比之下,GNU C89模式(在旧版本的GCC中默认使用)是C89标准以及许多扩展。 C89 doesn't have an inline keyword, but GCC recognizes it as an extension and just treats it as a hint to the optimizer. C89没有内联关键字,但GCC会将其识别为扩展名,只是将其视为对优化器的提示。

There are several ways to fix this problem: 有几种方法可以解决此问题:

  1. Change add to a static inline function. 更改添加到静态内联函数。 This is usually the right solution if only one translation unit needs to use the function. 如果只有一个翻译单元需要使用该功能,通常这是正确的解决方案。 static inline functions are always resolved within the translation unit, so you won't have to add a non-inline definition of the function elsewhere in your program. 静态内联函数始终在转换单元内解析,因此您不必在程序的其他位置添加该函数的非内联定义。
  2. Remove the inline keyword from this definition of add. 从add的此定义中删除inline关键字。 The inline keyword is not required for a function to be inlined, nor does it guarantee that it will be. 内联函数不需要inline关键字,也不能保证将其内联。 Some compilers ignore it completely. 一些编译器完全忽略它。 Clang treats it as a mild suggestion from the programmer. Clang将其视为程序员的温和建议。
  3. Provide an external (non-inline) definition of add somewhere else in your program. 提供在程序其他位置添加的外部(非内联)定义。 The two definitions must be equivalent! 这两个定义必须相等!
  4. Compile in the GNU C89 dialect by adding -std=gnu89 to the set of Clang options. 通过将-std = gnu89添加到Clang选项集,以GNU C89语言进行编译。 This option is only recommended if the program source cannot be changed or if the program also relies on additional C89-specific behavior that cannot be changed. 仅当程序源无法更改或程序还依赖于其他无法更改的C89特定行为时,才建议使用此选项。

All of this only applies to C code; 所有这些仅适用于C代码。 the meaning of inline in C++ is very different from its meaning in either GNU89 or C99. C ++中内联的含义与GNU89或C99中的含义大不相同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM