O2 中导致未定义符号的 gcc 优化标志

Posted

技术标签:

【中文标题】O2 中导致未定义符号的 gcc 优化标志【英文标题】:gcc optimization flags in O2 that causes undefined symbol 【发布时间】:2012-11-30 12:28:08 【问题描述】:

我在 gcc 4.5.2 中遇到了 -O2 问题。假设我有这个代码:

//file.cpp
void test::f() 
//file.h
struct test

    inline void f();
;

此代码在共享库中。现在,当我在没有 -O2 的情况下编译时,它工作正常。使用 -O2 表示 test::f() 是未定义的符号。显然 gcc 只是把它扔掉,因为它是“内联的”(尽管它实际上不是)。

我的问题是什么特定的优化标志会导致这种情况?我的想法是我想启用 -O2 但禁用该确切标志,以便我可以保持内联不受影响(这不是我的代码)。

我可能只是迭代所有这些,但这也可以是链接器标志,对吧?这工作太多了,我只是希望有人能提供线索。

【问题讨论】:

【参考方案1】:

标准要求inline 函数的定义存在于使用它的每个 TU 中。

要么删除inline,要么将函数的定义移动到头文件中。即使你想做的事情被允许,标记函数inline也没有任何好处。

碰巧在您的实现中,-O2 存在问题,但显然没有它就没有问题。

【讨论】:

我会检查 .h/.cpp 中的内联是否对 -O2 有帮助。至于去掉内联或者移动代码到表头,我做不到。 不,.cpp 中的内联没有帮助。 @queen3:您为什么认为在 .cpp 中使用内联会有所不同?这样做与 SteveJessop 的任何一个解决方案都不一致。 @queen3:我没有在 cpp 文件中说 add inlinef,我说的是从 @987654327 中删除 @ 在头文件中。如果您无法从标题中删除内联或移动定义,那么作为一种解决方法,您可以将f 的定义从file.cpp 复制并粘贴到每个调用f 的源文件中(或粘贴到新标题中)它们都包括在内)。不过要小心,因为现在你有重复的代码,如果它不同步,你会得到未定义的行为。你有重复代码的原因是你无法修改file.h,所以应该解决这个问题。 不,它不会阻止 me 编写正确的 C++,因为我不编写它。我只需要处理它。【参考方案2】:

最好的解决方案是修复或拒绝损坏的代码。内联函数必须在任何使用它们的翻译单元中定义,而这段代码违反了这一规则。

如果这不是一个选项,那么-fkeep-inline-functions 可能会很好地修补问题以允许代码编译和链接。

【讨论】:

不,-fkeep-inline-functions 花了 30 分钟 ld 并吃掉了 16GB 的内存(这是因为项目很大并且有很多内联函数 - 让它们都进入共享库是一个坏主意)。 @queen3:听起来你别无选择,只能修复损坏的代码。对不起。 我可以#define inline 并让 gcc 决定要内联的内容。但这感觉像是 hack,我更愿意做一个特定的优化标志或类似的东西。 @queen3:确实,某些函数(定义在头文件中和类定义之外的函数)必须声明为内联,因此删除所有使用 inline 会破坏以其他方式编码。如果您想使用优化标志,那么在每个级别启用的优化都会给出here。但是,请注意,我的编译器 (4.6.3) 在所有优化级别都拒绝您的代码,因此如果您升级编译器,您发现的任何问题都可能会破坏。 如果我#define inline __attribute__((weak)),有效的内联可能仍然可以在.h 中工作。我想最终我会回答我自己的问题。【参考方案3】:

您可以使用标志-fno-inline 强制gcc 忽略inline

【讨论】:

这与使用 -O2 的想法大相径庭。 @queen3 - 不,它与标记 inline 的东西冲突,而不是。

以上是关于O2 中导致未定义符号的 gcc 优化标志的主要内容,如果未能解决你的问题,请参考以下文章

哪个 gcc O2 标志可能导致 fp 计算失败?

未定义的参考 yaml-cpp

不可见的 GCC 优化标志?

使用 -O3 的冒泡排序比使用 GCC 的 -O2 慢

何时为 gcc 使用 -O2 标志?

ImportError:在 python 中导入 swigged c++-class 时未定义的符号