【问题标题】:Is this a reasonable hack to inline functions across translation units?这是跨翻译单元内联函数的合理破解吗?
【发布时间】:2013-06-28 05:49:22
【问题描述】:

我正在编写对性能敏感的代码,这确实需要我强制内联某些函数调用。

对于通过头文件在翻译单元之间共享的内联函数,通常必须将函数定义放在头文件中。我不想那样做。其中一些函数对不应在标头中公开的复杂数据结构进行操作。

我已经解决了这个问题,只需将所有 .h 和 .c 文件分别添加到一个 .c 文件中,这样就只有一个翻译单元。 (这会减慢重新编译的速度,但还不够重要。)

这将是“解决问题”,但是当一个 C 文件中的函数调用另一个 C 文件中应该是私有的函数时,它消除了出现错误,并且我想在这种情况下得到一个错误。所以,我有一个单独的 Makefile 条目,它执行“正常”构建,只是为了检查这种情况。

为了强制声明 inline 的函数在“正常”构建中很好地发挥作用,我实际上定义了一个宏 may_inline,它用于 inline 属性通常的位置。对于普通构建,它被定义为空,对于优化构建,它被定义为“内联”。

这似乎是一个可以接受的解决方案。我能看到的唯一缺点是我不能在具有相同原型的不同 .c 文件中拥有私有函数,但到目前为止,这对我来说并不是什么大问题。

另一个潜在的解决方案是使用GCC's Link-Time Optimization,它应该允许跨翻译单元内联。不过,这是一个新功能,我不相信它总是能按照我想要的方式内联。此外,我只能让它处理琐碎的问题,而不是我的实际代码。

这是一个可以接受的 hack,还是我做了一些非常愚蠢的事情?我以前从未见过这样做的事实让我有点紧张。

【问题讨论】:

  • GCC -flto 已经足够成熟(特别是在 GCC 4.8 中)可以用于生产。你应该信任它(在 GCC 4.8 中)
  • @BasileStarynkevitch 谢谢。那么,这是我的首选解决方案。对其他人:我仍然非常对我的问题的任何答案感兴趣,因为正如我所提到的,我可以让 -flto 解决玩具问题,但不是我的实际代码库。我不确定我是否能够找出问题所在。我最终可能会为此打开一个单独的问题。
  • 要记住的一件事是,如果您的各种 .c 文件在文件范围内使用 static 变量,那么如果它们具有相同的变量,您最终会得到不希望的和未诊断的共享名称和类型。
  • 我仍在研究它,但似乎我无法将 -flto 与 -std=c99 一起使用。删除 -std=c99 (这需要更新我所有的 for 循环)允许程序使用 -flto;但是,我的一些代码变慢了(或者我的分析工具坏了),如果我理解正确,这可能是 -flto 的“正确”行为。希望对此有一个积极的解决方案,但很可能在我的情况下 -flto 不是一个好的选择。
  • 你说的不应该暴露在header中是什么意思? ...暴露给谁?当只有一个翻译单元时,它们在 .C 文件中的公开方式与在 .H 文件中的公开方式一样。

标签: c gcc


【解决方案1】:

Unity 构建是一种绝对有效的方法,并且自古以来就在工业中得到广泛应用(参见例如this post)。最新版本的 Visual Studio 甚至为他们提供了builtin support

LTO 的缺点是即使在同一平台的编译器之间也不能移植。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-09
    • 1970-01-01
    • 1970-01-01
    • 2020-09-24
    相关资源
    最近更新 更多