使用 gcc 进行 fsanitize 导致意外提前退出

fsanitize with gcc causing unexpected early exit

我遇到一个错误无法始终重现,其中 free() 是在无效堆指针上调用的。使用有问题的代码根本不可能将此问题减少到 "minimal"——(一旦我这样做了,它就解决了)。我无法发现任何明显的问题(例如从未调用 calloc 的潜在情况,或双重释放等...)

我相信 valgrind 可以解决这个问题,除了对性能的影响过于极端(这些是客户端 -> 超时的服务器调用,以及开始时开销很大的操作...>在某些情况下为 4 秒)

这给我留下了 fsanitize=address,我相信?到目前为止,我在这方面的经验……不是很好。

我得到的是两个静态库和一个与它们链接的可执行文件。我已经为他们三个打开了 fsanitize=address。使用 -fsanitize=address,代码在 非常 彻底测试和正确的 init 例程期间在调试器下干净地退出(在 256 字节 memcpy 到 16 meg 的中间堆分配--退出代码 1).

任何有使用 fsanitize 实际经验的人都可以提供任何关于问题出在哪里的提示吗?我在 cmake 下使用 gcc/ld 并且代码(基本上)是用 C++ 编译的 C。如果可以改善情况,切换到 clang 可能是一个选择。

文件的典型编译命令:

"command": "/usr/bin/c++   -I. -I/home/redacted -fpermissive -g -g3 -fasynchronous-unwind-tables -fsanitize=address   
-std=gnu++11 -o core/CMakeFiles/nginx_core.dir/src/core/nginx.cpp.o -c /home/redacted.cpp",

我将把它留在这里,以供将来遇到 fsanitize 问题的搜索者使用。 tldr;--有效。我有两个基本问题:

  1. fsanitize 正在输出有关其退出原因的完整错误信息。这被 nginx 吞没了......并且在我们的定制版本中它被重定向到一个晦涩的日志文件。不知道为什么在 gdb 下我没有得到调试中断,但是......它检测到一个合法错误。此处的关键信息:在 __asan_report_error 中设置断点将在退出前停止程序,以便您可以检查各种帧。

  2. 虽然初始化例程是正确的并且经过严格测试,但正如我提到的,它确实需要其客户端正确分配(非平凡的)配置结构。在这种情况下,结构缺少 1 个字节,导致 1 个字节过读。