【问题标题】:Selectively inline functions (for debugging purposes)?选择性内联函数(用于调试目的)?
【发布时间】:2012-06-12 19:59:06
【问题描述】:

我想要的是一个构建配置,其中函数内联,除了一些选定的函数(可能内联也可能不内联,这将是由编译器决定)。

更好的是某种“内联级别”,我可以为每个函数指定这样的级别,加上构建时的最低级别,并且只有高于最低级别的函数才允许内联。我知道这没有标准的解决方案,但编译器特定的黑客同样受欢迎。

我希望能够在调试器中单步执行我的大多数非内联函数,但是应该内联其中的一些函数,部分原因是出于性能原因,部分原因是为了避免疯狂的深度调用堆栈。该代码涉及一些非常讨厌的模板元编程,但这部分已经完成,所以我想专注于其余部分。因此,最好将属于模板元程序的函数内联,而不是其他内联函数。

有没有办法实现这样的目标?

【问题讨论】:

  • 您可以使用预处理器宏,但您所描述的内容无法在运行时控制。
  • 这同样适用于模板。这也是在编译时修复的。
  • 感谢您的回复。我不想在运行时控制它。但是,我不确定您的意思,我将如何在这里使用宏?而不是内联函数?我想避免的。能够使用内联的所有内容(标准调试构建)或仅使用某些功能进行构建会很好;由编译器开关或类似的东西控制。

标签: c++ inline


【解决方案1】:

取决于您的编译器,是的。对于 g++,以下将起作用:

void foo() __attribute__ ((noinline));
void foo() __attribute__ ((always_inline));

在 MSVC++ 上:

__declspec(noinline) void foo();
__forceinline void foo();

请注意,g++ 要求属性仅应用于原型,而不是定义。因此,如果您的函数是仅定义的(没有单独的原型),那么您必须创建一个原型才能应用该属性。 MSVC 没有这个要求。

__forceinline 专门有some exceptions。确保您仔细阅读它们,以便您知道它是否会对您的特定情况产生任何影响。 g++ 没有记录always_inline 属性的任何异常,但有些事情是显而易见的(例如,内联对虚拟方法的调用仅在该方法被静态调用时才有效)。

您可以使用宏来概括这一点:

#ifdef _MSC_VER
 #define NOINLINE(x) __declspec(noinline) x
 #define INLINE(X) __forceinline x
#else
 #ifdef __GNUC__
  #define NOINLINE(x) x __attribute__ ((noinline))
  #define INLINE(x) x __attribute__ ((always_inline))
 #else
  #error "I don't know how to force inline/noinline on your compiler."
 #endif
#endif

INLINE(void foo());
NOINLINE(void foo());

【讨论】:

  • 谢谢。 __forceinline / always_inline 会覆盖相关的编译器开关(例如 MSVC 中的 /Ob0)吗?
  • @imre 我相信这是他们的目的,即覆盖编译器用来决定是否内联特定函数的任何和所有其他决策过程。
  • @imre : From the docs, no: "即使使用__forceinline,编译器也不能在所有情况下内联代码。编译器不能内联函数如果: ...函数或其调用者使用 /Ob0 编译(调试构建的默认选项)。"
  • @ildjarn 猜我在阅读时没有足够的向下翻页。好吧,这至少与对函数内联的精细控制一样接近。
【解决方案2】:

如果有一组你想要inlined的函数,你可以将#define一些宏(假设是GCC或Clang)转为__attribute__(__always_inline__),这将

  1. 始终内联函数
  2. 如果由于技术原因无法编译,则给出编译错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-17
    • 2011-06-27
    • 2010-11-06
    • 1970-01-01
    • 2019-12-23
    相关资源
    最近更新 更多