Ladybird 如何启用 Sanitizer 构建运行测试以复现 CI 的内存与未定义行为错误
2026/9/9 21:28:04 网站建设 项目流程

Ladybird 如何启用 Sanitizer 构建运行测试以复现 CI 的内存与未定义行为错误

【免费下载链接】ladybirdTruly independent web browser项目地址: https://gitcode.com/GitHub_Trending/la/ladybird

你在本地跑测试一切通过,代码提交后 CI 却挂了:Address Sanitizer 报出越界访问、内存泄漏,或者 Undefined Sanitizer 报出有符号整数溢出。Ladybird 的 CI 就是用 Address Sanitizer(ASan)和 Undefined Sanitizer(UBSan)插桩来运行 host 测试的,这两类工具能捕获内存泄漏、对栈/堆分配的越界访问、有符号整数溢出等常见 C++ 错误。要复现 CI 上的失败,本地就必须用同样的 Sanitizer 插桩重新配置构建,再用 CMake 的Sanitizer预设跑测试。

CI 上到底开了什么

先明确要复现的目标。据 Testing.md 的 "Running with Sanitizers" 一节:

  • CI 运行 host 测试时启用了Address SanitizerUndefined Sanitizer插桩;
  • 这两个工具覆盖的错误类型包括:内存泄漏、对栈和堆分配的越界访问、有符号整数溢出等;
  • Sanitizer 构建比非 Sanitizer 构建耗时明显更长,并且会干扰ccache等工具的缓存。

对应的 CMake 选项是ENABLE_ADDRESS_SANITIZERENABLE_UNDEFINED_SANITIZER。这两个选项在 Meta/CMake/cmake_options.cmake 中定义,默认均为OFF,实际生效时由 Meta/CMake/sanitizers.cmake 添加-fsanitize=address -fno-omit-frame-pointer-fsanitize=undefined -fno-omit-frame-pointer等编译与链接选项。

准备条件

Sanitizer 构建走的是标准 CMake 构建流程,前提与常规构建一致,参见 BuildInstructionsLadybird.md:

  • Qt6.9+ 开发包、nasm及额外构建工具;
  • 支持 C++23 的编译器(CI 使用 gcc-14 与 clang-21);
  • Rust 工具链;
  • $PATH中可用 CMake 3.30 或更新版本(CMakePresets.json 也要求cmakeMinimumRequired3.30)。

Sanitizer构建预设的 description 写明它适用于 Unix("Build the project with Sanitizers on Unix"),即 Linux/macOS/类 Unix 环境。

主路径:用 Sanitizer 预设配置、构建并运行测试

最简单的启用方式就是Sanitizer预设,三条命令:

cmake --preset Sanitizer cmake --build --preset Sanitizer ctest --preset Sanitizer

这三个预设分别定义在 CMakePresets.json 与各平台的 include 预设(如 Meta/CMake/presets/CMakeUnixPresets.json)中,底层配置来自 Meta/CMake/presets/CMakeBasePresets.json 的Sanitizer_base。该配置值得注意的几点:

  • CMAKE_BUILD_TYPERelWithDebInfo(不是 Debug);
  • 同时置ENABLE_UNDEFINED_SANITIZER=ONENABLE_ADDRESS_SANITIZER=ON
  • 构建目录为Build/sanitizers,与Build/releaseBuild/debug等常规构建目录互不干扰,可以并存。

测试预设Sanitizer继承的root_base还会设置LADYBIRD_SOURCE_DIR为仓库根目录(${fileDir})——文档明确说明部分测试依赖该环境变量指向 ladybird 源码树根。同时它已替你设置好与 CI 一致的运行时选项:

ASAN_OPTIONS: strict_string_checks=1:check_initialization_order=1:strict_init_order=1:detect_stack_use_after_return=1:allocator_may_return_null=1 UBSAN_OPTIONS: print_stacktrace=1:print_summary=1:halt_on_error=1

文档原话是:「为了让测试行为与 CI 一致,请确保正确设置 ASAN_OPTIONS 和 UBSAN_OPTIONS。Sanitizer 测试预设已经设置了这些环境变量。」所以走预设路径时无需再手动 export。

如何判断结果

测试预设的base配置(见 Meta/CMake/presets/CMakeBasePresets.json)设置了outputOnFailure: truestopOnFailure: true,即ctest --preset Sanitizer遇到第一个失败测试就会停在那里,并自动打印失败测试的输出——Sanitizer 触发的错误报告就会出现在这个位置。如果失败输出不足以定位,Testing.md 还给出两个通用手段:

CTEST_OUTPUT_ON_FAILURE=1 ninja test # 在构建目录下,查看失败测试的 stdout/stderr # 或直接使用 ctest ctest --output-on-failure

判断标准是文档中实际展示的机制:某个 host 测试在 Sanitizer 插桩下触发错误报告并导致测试失败、ctest停止(stopOnFailure),即说明你在本地复现了 CI 上的一类失败;全部测试通过则与 CI 的 Sanitizer 运行结果一致。文档没有给出固定的成功日志格式,实际输出以你本机构建的 ctest 结果为准。

替代路径:手动配置(不经预设)

如果你想完全控制配置,或者想在已有构建(如Build/lagom)上启用 Sanitizer,Testing.md 给出的是这套命令。注意${PWD}在该命令序列中代表Build/lagom目录,LADYBIRD_SOURCE_DIR因此指向其两级上溯的仓库根:

export ASAN_OPTIONS='strict_string_checks=1:check_initialization_order=1:strict_init_order=1:detect_stack_use_after_return=1:allocator_may_return_null=1' export UBSAN_OPTIONS='print_stacktrace=1:print_summary=1:halt_on_error=1' cmake -GNinja -B Build/lagom -DENABLE_ADDRESS_SANITIZER=ON -DENABLE_UNDEFINED_SANITIZER=ON cd Build/lagom ninja CTEST_OUTPUT_ON_FAILURE=1 LADYBIRD_SOURCE_DIR=${PWD}/../.. ninja test

手动路径与预设路径的差异在于:环境变量需要你自己 export(预设是替你在ctest时注入),LADYBIRD_SOURCE_DIR需要自己导出,否则会漏掉依赖它的测试。

限制与可选调整

  • 构建耗时与缓存:文档明确警告 Sanitizer 构建比非 Sanitizer 构建慢得多,且会弄脏ccache缓存,规划复现时间时要预留余量。
  • UBSan 恢复行为:默认 UBSan 报告后可继续执行。AdvancedBuildInstructions.md 提供了UNDEFINED_BEHAVIOR_IS_FATAL选项,把所有未定义行为 Sanitizer 错误变为不可恢复,并降低ENABLE_UNDEFINED_SANITIZER的性能开销。对已有构建目录调整此类布尔选项,用cmake <binary_dir> -DVAR_NAME=Value重新配置即可(同一文档的 "CMake Cache Manipulation" 一节)。
  • Memory Sanitizer 是另一个选项ENABLE_MEMORY_SANITIZER针对未初始化内存访问检查(Lagom 测试用例),预设Sanitizer并没有开启它,它对应的是与 CI 的 ASan+UBSan 不同的检查面,只有在你的问题涉及未初始化内存时才考虑单独启用。
  • Windows 原生构建:BuildInstructionsLadybird.md 说明 Windows 上支持的方式是 WSL2(原生构建仍为实验性),本文的预设路径同样以 Unix 环境为准。

复现失败之后,下一步就是结合报告中指出的分配/释放栈定位引入错误的改动;若报告中符号信息不全,可回看 AdvancedBuildInstructions.md 中关于调试符号与优化级别的说明。

【免费下载链接】ladybirdTruly independent web browser项目地址: https://gitcode.com/GitHub_Trending/la/ladybird

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询