说我在源文件中有这个小功能
static void foo() {}
并且我构建了二进制文件的优化版本,但我不想内联此函数(出于优化目的)。我可以在源代码中添加宏以防止内联吗?
说我在源文件中有这个小功能
static void foo() {}
并且我构建了二进制文件的优化版本,但我不想内联此函数(出于优化目的)。我可以在源代码中添加宏以防止内联吗?
Answers:
您需要gcc
-specific noinline
属性。
此函数属性可防止考虑对函数进行内联。如果该函数没有副作用,则可以进行优化,除了内联之外,还可以使函数调用被优化,尽管函数调用是实时的。为了避免优化此类通话,请放置
asm ("");
像这样使用它:
void __attribute__ ((noinline)) foo()
{
...
}
GCC有一个名为
-fno-inline-small-functions
因此,在调用gcc时使用它。但是副作用是所有其他小的函数也未内联。
-fno-inline
根本不起作用。gdb
仍然在跨步时输入方法。东西坏了,我怀疑是这样gdb
。
我知道问题是关于GCC的,但是我认为了解一些有关编译器和其他编译器的信息可能会很有用。
GCC的
noinline
function属性在其他编译器中也很流行。它至少受以下方面的支持:
__has_attribute(noinline)
)__TI_GNU_ATTRIBUTE_SUPPORT__
)此外,MSVC还支持
__declspec(noinline)
Visual Studio 7.1。英特尔可能也支持它(他们试图与GCC和MSVC兼容),但是我没有费心去验证这一点。语法基本相同:
__declspec(noinline)
static void foo(void) { }
PGI 10.2+(可能更旧)支持noinline
适用于下一个功能的编译指示:
#pragma noinline
static void foo(void) { }
TI 6.0+支持一种
FUNC_CANNOT_INLINE
杂用功能(烦人)在C和C ++中的工作方式不同。在C ++中,它类似于PGI:
#pragma FUNC_CANNOT_INLINE;
static void foo(void) { }
但是,在C中,函数名称是必需的:
#pragma FUNC_CANNOT_INLINE(foo);
static void foo(void) { }
Cray 6.4+(可能更早)采用类似的方法,要求函数名称:
#pragma _CRI inline_never foo
static void foo(void) { }
Oracle Developer Studio还支持使用函数名称的编译指示,至少可以追溯到Forte Developer 6,但是请注意,即使在最新版本中,它也必须位于声明之后:
static void foo(void);
#pragma no_inline(foo)
根据您的献身精神,您可以创建一个可在任何地方使用的宏,但是您需要将函数名称以及声明作为参数。
如果OTOH,您对大多数人都可以使用的东西还可以,那么您可以摆脱一些美学上令人愉悦并且不需要重复的事情。这就是我为Hedley采取的方法,其中HEDLEY_NEVER_INLINE的当前版本 如下所示:
#if \
HEDLEY_GNUC_HAS_ATTRIBUTE(noinline,4,0,0) || \
HEDLEY_INTEL_VERSION_CHECK(16,0,0) || \
HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
HEDLEY_TI_VERSION_CHECK(8,0,0) || \
(HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
# define HEDLEY_NEVER_INLINE __attribute__((__noinline__))
#elif HEDLEY_MSVC_VERSION_CHECK(13,10,0)
# define HEDLEY_NEVER_INLINE __declspec(noinline)
#elif HEDLEY_PGI_VERSION_CHECK(10,2,0)
# define HEDLEY_NEVER_INLINE _Pragma("noinline")
#elif HEDLEY_TI_VERSION_CHECK(6,0,0)
# define HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
#else
# define HEDLEY_NEVER_INLINE HEDLEY_INLINE
#endif
如果您不想使用Hedley(这是一个公共域/ CC0标头),则可以毫不费力地转换版本检查宏,但超出我的意愿。
我使用gcc 7.2。我特别需要一个非内联函数,因为它必须在库中实例化。我尝试了__attribute__((noinline))
答案以及asm("")
答案。没有人解决问题。
最终,我发现在函数内部定义静态变量将迫使编译器在静态变量块中为其分配空间,并在首次调用该函数时对其进行初始化。
这是一个肮脏的把戏,但它可以工作。
inline void foo(void) { ... }
在标头中定义函数,然后extern inline void foo(void);
在库源文件中声明它。按照C99语义,允许编译器在需要时内联函数并在库中发出目标代码。请参阅在C99中没有“静态”或“外部”的“内联”是否有用?。