从 C++14 升级到 C++17(Ubuntu 18.04,GCC 7.5.0)时,我们一直在努力解决这个非常奇怪的问题。该工具链是 Linaro 在 Jetson TX2 上的,是默认的。
背景:
我们有一个 C++ 应用程序,它使用我们在 Ubuntu 18.04 上开发的A
库中的算法。构建和广泛的系统测试已经运行了L
两年。Intel
Jetson TX2
现在我们决定升级到 C++17(-std=c++1z with GCC)。我们首先在启用 C++17 的情况下进行构建L
,起初一切似乎都运行良好,但后来我们注意到一些测试运行开始在 ARM 上出现奇怪的行为。就像 30 个测试中的 2 个测试一样,这是确定性的(!)。
然后我们开始调查并注意到库中的一个构造函数接受const std::pair<float, float> &
了某种损坏的数据。内部构造函数.first
似乎是.second
并且.second
总是0
。像这种奇怪的东西。
因此,如果A
仍在 C++14 上并且L
在 C++17 上,就会发生这种情况。
好的。
然后我们反过来尝试了这个。L
在 C++14 和A
C++17 上的应用程序。结果是相似的。一些测试开始失败(虽然不一样)并且它是确定性的。根本原因还是一样的:不知何故std::pair<float, float>
,API 搞砸了。
所以到目前为止的组合是这样的:
A: C++14, L: C++14, Intel => OK
A: C++14, L: C++17, Intel => OK
A: C++17, L: C++14, Intel => OK
A: C++17, L: C++17, Intel => OK
A: C++14, L: C++14, ARM => OK
A: C++14, L: C++17, ARM => FAIL
A: C++17, L: C++14, ARM => FAIL
A: C++17, L: C++17, ARM => OK
显然这是一个大型商业应用程序,所以我不能在这里复制粘贴代码。我首先怀疑这将是一个编译器错误(它仍然可能是),但它似乎太明显了!
还有更多:
我们最近还注意到,如果我们只用const std::pair<float, float> &
简单float
的参数替换 ,测试就会再次通过。
任何猜测到底是怎么回事?编译器错误?切换到 C++17甚至在理论上会导致这样的事情(编译器完全相同)?尤其是这样(升级哪个组件都没有关系)。
我们只是没有发现 API 有什么问题。它已经使用 C++14 在 Intel 和 ARM 上运行了将近两年,没有任何问题。
编辑:设法制作一个工作示例项目: https ://drive.google.com/open?id=1B5SceFB1mKkCnE8iE59Mq0lScK2F0iOl
说明和示例输出README.md
此示例在 Intel 和 Jetson TX2 上的输出:
On Intel (Ubuntu 18.04, GCC 7.5.0) this app prints:
$ ./app/App
S: 42
L: 3.14
R: 666
In Foo::update(): s: 42
In Foo::update(): l: 3.14
In Foo::update(): r: 666
On Jetson TX2 (Ubuntu 18.04, GCC 7.5.0 / Linaro) this app prints:
$ ./app/App
S: 42
L: 0
R: 2.39152e+29
In Foo::update(): s: 42
In Foo::update(): l: 0
In Foo::update(): r: 2.39152e+29