如何内联仅用于发布版本的函数
// common.h
// This is foo function. It has a body.
__inline void foo() { /* something */ }
// a.cpp
#include "common.h" // for foo function
// Call foo
// b.cpp
#include "common.h" // for foo function
// Call foo
我只想在构建发布时内联 foo 函数。我不想为 Debug
构建内联函数。
我尝试过,但链接器错误让我很恼火。
在本例中,foo
函数的主体在 common.h 头文件中定义。
所以如果我这样做的话,
//common.h
#if !defined(_DEBUG)
__inline
#endif
void foo() { /* something */ }
它将在 DEBUG
构建中遇到链接错误。因为两个模块试图包含 common.h。
我不知道如何解决它。
是否可以?
// common.h
// This is foo function. It has a body.
__inline void foo() { /* something */ }
// a.cpp
#include "common.h" // for foo function
// Call foo
// b.cpp
#include "common.h" // for foo function
// Call foo
I would like to inline the foo function only when I build for release. I don't want to inline functions for Debug
build.
I tried it but linker errors annoyed me.
In this case, foo
function's body is defined in common.h header file.
so if I just do
//common.h
#if !defined(_DEBUG)
__inline
#endif
void foo() { /* something */ }
It will be met a link error in DEBUG
build. Because two modules try to include common.h.
I have no idea to solve it.
Is it possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
“简单”的解决方案是这样的:
static
对于消除链接错误和绕过单一定义规则是必要的。一个更好的解决方案是简单地禁用内联项目范围内的调试。 GCC 支持
-wno-inline-functions
和-fno-inline-small-functions
选项来抵消这些优化,而且它也不为-O1
或更低版本启用内联(也可能为-Os
)。大多数编译器都有类似的选项。我称后者为更好的解决方案,因为它应该指示编译器忽略内联提示,从而消除对讨厌的预处理器指令的需要。
The "easy" solution would be this:
static
is necessary to silence linking errors and get around the One Definition Rule.A better solution would be to simply disable inlining project wide for debugging. GCC supports the
-wno-inline-functions
and-fno-inline-small-functions
options to counteract those optimizations, and it also does not enable inlining for-O1
or lower (and probably-Os
as well). Most compilers have similar options.I call the latter a better solution because it should instruct the compiler to ignore the
inline
hint, eliminating the need for pesky preprocessor directives.需要认识到的基本一点是,
inline
关键字(或 Microsoft 的 C 语言__inline
扩展 - 因为 MSVC 不支持 C99)本质上是违反单一定义规则的通行证。如果您考虑一下 - 这就是它的全部内容,因为编译器没有义务实际执行任何内联。因此,当您有一个内联函数时,您可以在多个模块中定义该函数。事实上,您有义务在实际使用该函数的任何模块中定义它。
但是,如果您不将该函数声明为内联函数,则必须确保您的定义不超过一个(如果实际使用则只有一个)。对于非成员函数(C 中的所有函数),有几种方法可以解决此问题:
static
以更改其与内部的链接(请注意,您可以使用static inline< /code> 函数开始)。
基本上,您需要做的是在单独的 .c 文件中实现该函数,就像您遵循每个模块单个函数编码标准的传统一样(实际上您也可以这样做将几个内联函数放入 .c 模块中 - 但它们应该全部内联或不内联作为一个组,以防止事情变得过于失控)。该函数的实现需要安排为能够包含在标头中 - 因此它需要包含防护,就像任何其他标头一样。然后,当您需要内联函数时,您可以使用预处理器有条件地将实现作为标头的一部分包含在内(因此该实现将可用于所有模块),但如果您不内联,则不要包含它(因此您遵循在这种情况下的定义规则):
common.h
标头:// 通用.h
#ifndef COMMON_H
#define COMMON_H
foo()
的实现:以及一个示例程序:
现在,如果您编译发布:
foo()
将是内联
(或__inline
(视情况而定)。如果您编译为非发布:
您有一个非内联
foo()
。编译器和链接器在这两种情况下都很满意。
话虽如此,我有点喜欢将
INLINE
重新定义为static
以便进行调试的建议。然而,最终我不确定我是否真的看到了这一点 - 现代调试器能够单步执行内联函数,并且如果禁用,调试器可能不会内联函数调用优化。因此,您也可以在内联函数中设置断点,并使其在非优化构建中正常工作。
我不确定你的最终目标到底是什么。在调试/非优化构建中将函数保留为内联有什么缺点?
The fundamental thing to realize is that the
inline
keyword (or Microsoft's__inline
extension for C - since MSVC doesn't support C99) is essentially a pass to violate the one definition rule. If you think about it - that's all it really is, since the compiler is under no obligation to actually perform any inlining.So, when you have an
inline
function you're allowed to have the function defined in more than one module. In fact, you're obligated to have it defined in any module that actually uses the function.However, if you don't declare the function as
inline
, you have to ensure that you have no more than one definition (exactly one if it actually gets used). For non-member functions (all function in C), there are a few ways around this:static
to change it's linkage to internal (note that you can havestatic inline
functions to begin with).Basically, what you need to do is have an implementation of the function in a separate .c file, just like if you were following the tradition of a-single-function-per-module coding standard (actually you can do this just as well putting several inline functions in the .c module - but they should all be inline or not inline as a group to keep things from getting too out of hand). The implementation of the function needs to arrange to be able to be included in a header - so it needs include guards, just like any other header. Then you use the preprocessor to conditionally include the implementation as part of the header when you want inline functions (so the implementation will be available to all modules), but don't include it if you're not inlining (so you follow the one definition rule in that case):
The
common.h
header:// common.h
#ifndef COMMON_H
#define COMMON_H
The implementation of
foo()
:And an example program:
Now if you compile for release:
foo()
will beinline
(or__inline
as the case may be).If you compile for non-release:
you have a non-inline
foo()
.And both the compiler and linker are happy in either case.
All that said, I kind of like the suggestion to maybe redefine
INLINE
to bestatic
for debugging purposes.However, ultimately I'm not sure I see the point to any of this really - modern debuggers are able to step through functions that are
inline
, and the debugger probably won't inline function calls if you disable optimizations. So you can set breakpoints inside the inline function as well and have it work fine in non-optimized builds.I'm not sure exactly what you're end-goal in this really is. What's the drawback to leaving the functions as
inline
in debug/non-optimized builds?您不能将仅标头函数声明为非内联。您可以将它们声明为静态(也称为 C 风格静态),但这将在每个翻译单元中生成函数的副本(包括局部静态变量,如果有)。更好的解决方案是将其保留为内联。在调试模式下,当禁用优化时,编译器通常不会内联任何函数。
You can't declare header only functions as non-inline. You could declare them as static (a.k.a. C-style static), but that will generate a copy of the function (including local static variables, if any) in each translation unit. A better solution is to leave it as inline. In debug mode when optimizations are disabled compilers usually don't inline any functions.
然后
为发布版本定义RELEASE。当然你可以从这里看到有很多方法可以做到。
Then
then define
RELEASE
for the release version. of course you can see from this there are lots of ways to do it.在大多数情况下,未定义发布标志。通常会定义调试标志。
_DEBUG是大多数编译器定义的,因此不需要定义发布标志:
更实用:
In most cases release flags are not defined. Typically debug flags are defined.
_DEBUG is defined by most compilers, so there is no need to define a release flag:
More practical:
使用编译器条件并定义编译时标志。
示例:
Use compiler conditionals and define a compile time flag.
Example: