2017-02-16 62 views
-1

我有一些单元测试失败,由于一些数学计算返回意外的结果。make/gcc:“糟糕的构建”的可能原因是什么?

  • 代码本身已知是正确的。
  • 构建系统并没有改变
  • 编译器标志并没有改变

我们使用的cmake生成的生成文件我们,这给了我一个高水平的信心,makefile文件是正确的。

该构建已经运行了很多个月,而这正是这种特殊的,不寻常的虚假故障,因此这个问题。

我查看了失败测试的目标文件,并且正如所料,它比源文件更新,所以make认为它不需要重新编译它。

-rw------- 1 steve steve 64578 Feb 7 11:13 foo_tests.cc 
-rw------- 1 steve steve 12930760 Feb 14 13:18 foo_tests.cc.o 

如果我删除对象文件并重建,测试现在通过。

-rw------- 1 steve steve 12931080 Feb 16 13:57 foo_tests.cc.o 

我注意到新的目标文件稍大。这有点令人费解。

  • 什么会导致这样的糟糕构建?

  • 有什么我可以做的,以检测一个坏的构建之前,运行它,并发现虚假的错误?

构建细节:

这是使用cmake生成与生成文件释放模式二进制,并使用在CentOS 7.2 GCC 5.2.1

我们使用的编译器标志构建的:

CXX_FLAGS 
-Werror 
-Wall 
-Wextra 
-m64 
-msse2 
-msse4.2 
-mfpmath=sse 
-ftemplate-depth-128 
-Wno-unused-parameter 
-Wno-maybe-uninitialized 
-Wno-strict-aliasing 
-pthread 
-DBOOST_DATE_TIME_POSIX_TIME_STD_CONFIG 
-ggdb2 
-DNDEBUG 
-O3 
-funroll-loops 
-fdevirtualize 
-finline-functions 
-fno-builtin-malloc 
-fno-builtin-calloc 
-fno-builtin-realloc 
-fno-builtin-free 

LINKER_FLAGS: 
-m64 
-rdynamic 
+0

_“有什么事情可以在运行之前检测到错误的构建并发现虚假错误?”_有些构建系统允许执行_dry runs_。 –

+2

投票结束太宽泛。有太多的东西可能导致构建破坏。 –

+0

'.cc'文件使用的某个头文件可能已更改,但makefile并未列出头文件作为'.o'文件的先决条件。也许源文件上的时间戳被错误地重置为某个较旧的值,或者'.o'文件上的时间戳被错误地更新而不重建它。没有看到你的makefile和/或知道更多关于你的设置,这是不可能的。 – MadScientist

回答

1
  • 瓦在这可能会导致这样的糟糕构建?

最可能的原因是糟糕的源代码,其中“坏”可以简单地意味着过时。如果你的makefile没有表达全部每个目标的依赖关系,那么有可能make在真正需要重建时无法重建某些组件。结果可能是不能正确协同工作的对象文件的集合。

另一种可能性是错误或不一致的编译器选项。如果程序的行为取决于编译器选项(符号定义在这里是一个特别可能的罪魁祸首),并且您使用错误的选项构建组件,那么更改选项通常不足以说服make重建任何东西。在这种情况下,干净的版本是最好的策略。

鉴于您的“坏”构建仍然会产生可以链接到工作(尽管不正确)程序的对象,并且删除该对象文件并使用相同的工具链重建它会导致具有不同行为的不同对象文件,我没有看到其他可能的选择。

  • 有什么我可以做检测到不良构建之前,运行它,并发现虚假错误?

假设构建事实上成功的第一个地方,没有。这是测试之一。但请注意,执行失败的构建是进入成功但糟糕的构建的入口,因为我描述的任何一类问题。

+0

我相信所有的依赖关系都已正确列出,因为构建已经工作了几个月,没有任何修改构建系统,编译器标志或其他。我们使用cmake,我期望在创建目标和依赖关系链接时获得正确的依赖关系。在过去,我也注意到当我更改编译器标志cmake时,会导致所有受影响的目标被视为过期。这就是这种特殊的,不寻常的虚假失败,因此是一个问题。 –

+0

@SteveLorimer,对我来说,底线是“坏”构建产生了一个明显有效的对象文件,因为它可以链接到一个只能产生不正确结果的可运行可执行文件。除了测试它之外,没有什么好方法可以检测到这种错误构建,因为代码的运行时行为是唯一表明它存在任何问题的事情。 –

+0

好的,谢谢你的输入。非常迷惑! –

相关问题