a.c
视为内存泄漏 MRE:#include <stdlib.h>
void Foo() { malloc(1); }
int main() { Foo(); return 0;}
$ clang++ -g -fsanitize=address a.c; ./a.out
=================================================================
==...==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 1 byte(s) in 1 object(s) allocated from:
#0 0x... in malloc (/.../a.out+0xa114e) (BuildId: ...)
#1 0x... in Baz() (/.../a.c:2:14
#2 0x... in main (/.../a.c:3:14
#3 0x... in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
SUMMARY: AddressSanitizer: 1 byte(s) leaked in 1 allocation(s).
要获得合理的性能,请添加
或更高。-O1
-O1
):$ clang++ -O1 -g -fsanitize=address a.c; ./a.out
使用代码优化级别 1 或更高级别时,Clang LeakSanitizer 仍然可以检测到内存泄漏吗?
如果答案是是,请提供一个最小的可重现示例(MRE)来证明这一点。
如果答案是否,请解释为什么(链接到 Clang 编译器源代码,...)。
Clang LeakSanitizer文档Usage部分没有明确提到不应使用代码优化。
以上观察结果是使用 18 版 Clang 进行的,使用 LLVM 自动安装脚本安装在 Linux Ubuntu 22.04.3 上。
正如 user17732522 在 comment 中所解释的,当使用
a.c
选项时,背景部分中的 -O1
文件示例不会导致内存泄漏检测,因为:
优化后的程序不会有任何实际的内存泄漏。 malloc 调用将被优化,因为它不会影响可观察的行为
你的最小示例是太小了——
clang
能够优化一切远离它:
(gdb) disas main
Dump of assembler code for function main:
0x0000000000401120 <+0>: xor %eax,%eax
0x0000000000401122 <+2>: ret
如您所见,
Foo
或 malloc
都没有保留。
为了让它更真实一点,试试这个:
#include <stdlib.h>
#include <stdio.h>
void* Foo() { return malloc(1); }
void Bar(void *p) { printf("p = %p\n", p); }
int main() { Bar(Foo()); return 0;}
clang -g -O0 -fsanitize=address a1.c && ./a.out
p = 0x502000000010
=================================================================
==191==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 1 byte(s) in 1 object(s) allocated from:
#0 0x4c8822 in malloc (/tmp/a.out+0x4c8822) (BuildId: a27851507d14179bca1fa40aa114a3e5ffa99c23)
#1 0x50644d in Foo /tmp/a1.c:4:22
#2 0x506493 in main /tmp/a1.c:6:18
#3 0x7f9a74195149 in __libc_start_call_main (/lib64/libc.so.6+0x28149) (BuildId: 7ea8d85df0e89b90c63ac7ed2b3578b2e7728756)
#4 0x7f9a7419520a in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x2820a) (BuildId: 7ea8d85df0e89b90c63ac7ed2b3578b2e7728756)
#5 0x42a324 in _start (/tmp/a.out+0x42a324) (BuildId: a27851507d14179bca1fa40aa114a3e5ffa99c23)
SUMMARY: AddressSanitizer: 1 byte(s) leaked in 1 allocation(s).
现在与
-O1
:
clang -g -O1 -fsanitize=address a1.c && ./a.out
p = 0x502000000010
=================================================================
==197==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 1 byte(s) in 1 object(s) allocated from:
#0 0x4c8822 in malloc (/tmp/a.out+0x4c8822) (BuildId: 1ffaa6630367e5a8f0a95663181cd0d01efdc513)
#1 0x50646a in Foo /tmp/a1.c:4:22
#2 0x50646a in main /tmp/a1.c:6:18
#3 0x7f804f1c020a in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x2820a) (BuildId: 7ea8d85df0e89b90c63ac7ed2b3578b2e7728756)
#4 0x42a324 in _start (/tmp/a.out+0x42a324) (BuildId: 1ffaa6630367e5a8f0a95663181cd0d01efdc513)
SUMMARY: AddressSanitizer: 1 byte(s) leaked in 1 allocation(s).