首页 > 解决方案 > Instrumentation:融合 gcov / ASan 还是拆分成独立的构建(+ 后续测试)?

问题描述

在我的(基于 linux 的)CI/CD 管道中,我目前正在做(基本上):

这现在基于 GCC 10。

在考虑添加基于 Sonarqube 的分析时(这意味着使用构建包装器,希望它与描述的一样非侵入性 -> 由于有些害怕,我什至考虑了第三次构建!),我想知道我采取的原始方法:

将代码覆盖和内存清理工具融合到一个构建中是否安全/正确/一个好主意?

与独立构建相比,我是否有可能失去某些东西(例如 ASan 推理的能力、覆盖计数准确性、非线性减速)(遗憾的是,这增加了我们需要运行两次测试所需的时间)?

编辑:

对于它的价值,关于使用 gcov/asan对我来说意味着什么的更多细节(是的:它不像 cmake-def 的其他部分那样干净):

# Code Coverage Analysis
option(ENABLE_CODE_COVERAGE_ANALYSIS "Enable instrumentalization-based code-coverage" OFF)
if (${ENABLE_CODE_COVERAGE_ANALYSIS})
  message(STATUS "Instrumentalize for code-coverage analysis.")
  add_definitions(--coverage)
  set(COV_LINKING gcov)
endif()

# ASAN Memory Sanitization
option(ENABLE_ASAN "Enable ASAN" OFF)
if (${ENABLE_ASAN})
  message(STATUS "Instrumentalize for ASAN")
  set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
  set (CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")
  # suppress GRPC ASAN stuff
  # https://github.com/grpc/grpc/pull/22325/files
  add_definitions("-DGRPC_ASAN_SUPPRESSED")
endif()

标签: c++gccg++gcovaddress-sanitizer

解决方案


如果您有测试验证非常短的时间,那么这些测试无论如何都应该使用 Release 类型的编译运行(没有调试,所以也没有消毒剂,并且完全优化)。

任何其他测试,那些验证与时间相反的正确性的测试,都应该在完全调试、清理、覆盖和不优化的情况下运行。这会增加您及早发现问题的机会。

就我而言,我在进行开发时有三种通用模式:

  1. 调试
  2. 消毒剂(带调试)
  3. 发布

在大多数情况下,我使用 Debug 运行,当似乎存在内存问题时,我使用 Sanitizer 版本进行测试。

但是,当准备好运行覆盖测试时,我会运行一个脚本,该脚本会打开调试、清理程序、覆盖并删除所有优化。当我运行这个脚本时,它做的第一件事就是删除 COVERAGE 文件夹并重建所有内容,例如,它可能是这样的(删除了错误检查):

SOURCE=`pwd`
rm -rf ../COVERAGE
cd ../COVERAGE
cmake $SOURCE
make -DCOVERAGE=ON -DSANITIZER=ON -DCMAKE_BUILD_TYPE=Debug ...
tests/unittests
lcov ...
genhtml ...

所以我现在已经运行了一段时间,但我没有需要计时的测试。话虽如此,使用该getrusage()功能,我可以添加计时测试。在大多数情况下,这并不是真正让我觉得有用的东西。特别是因为时间非常依赖于外部事物,例如 CPU、网络、SSD 与 HDD 等。

我的旧电脑的主要问题是内存。使用消毒剂会使用更多的 RAM,因此如果您必须能够在较小的系统上运行测试(例如具有 4Gb RAM 的 VirtualBox 计算机),那么它可能变得不可行。在我的新电脑上,我有 512Gb 的 RAM,所以我没有这个问题。


推荐阅读