我最近将我的Linux开发VM从Ubuntu 16.04升级到了18.04,并注意到一件事情发生了变化。这是在x86-64上。在16.04版中,我一直都有这个工作流程,用于构建要使用gcc(5.4,16.04中的库存版本)以及-fsanitize=address-O0 -g的项目,然后通过gdb(7.11.1,以及Ubuntu随附的版本)。这样做很好,最后,如果LeakSanitizer检测到内存泄漏,将生成泄漏报告。

在18.04中,这似乎不再有效; LeakSanitizer提示在ptrace下运行:

==5820==LeakSanitizer has encountered a fatal error.
==5820==HINT: For debugging, try setting environment variable LSAN_OPTIONS=verbosity=1:log_threads=1
==5820==HINT: LeakSanitizer does not work under ptrace (strace, gdb, etc)

然后程序崩溃:
Thread 1 "spyglass" received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51

我不确定是什么导致了新的行为。在18.04上,我使用默认的gcc(7.3.0)进行构建,使用-fsanitize=address -O0 -g并使用默认的gdb(8.1.0)进行调试。可以以某种方式重新启用旧行为吗?还是我需要更改工作流程并从程序中分离出来才能杀死它以获取泄漏报告?

最佳答案

LeakSanitizer在内部使用ptrace,可能会挂起所有线程,以便它可以扫描泄漏而不会产生误报(请参阅issue 9)。只有一个应用程序可以使用ptrace,因此,如果您在gdb或strace下运行应用程序,则LeakSanitizer将无法通过ptrace进行附加。

如果您对泄漏调试不感兴趣,请禁用它:

export ASAN_OPTIONS=detect_leaks=0

如果确实要启用泄漏调试,则必须在LeakSanitizer开始扫描之前分离调试器。为了不久之后可以连接调试器,请稍睡一会儿(例如10秒):
export ASAN_OPTIONS=sleep_before_dying=10
./program

然后在另一个 shell 中,再次附加到应用程序:
gdb -q -p $(pidof program)

有关上述(和其他)选项的更多说明,请参见https://github.com/google/sanitizers/wiki/AddressSanitizerFlags

09-16 10:09