我在项目中使用了 -fsanitize=leak
和 -fsanitize=address
。 我原以为leak可以找到内存泄漏(未释放的内存),而address可以找到错误的内存访问。 但是address也会报告未删除的内存泄漏。那么,-fsanitize=leak
的作用是什么呢?
我在项目中使用了 -fsanitize=leak
和 -fsanitize=address
。 我原以为leak可以找到内存泄漏(未释放的内存),而address可以找到错误的内存访问。 但是address也会报告未删除的内存泄漏。那么,-fsanitize=leak
的作用是什么呢?
地址(Address)检测器会执行一些额外的操作,例如检查是否在写入越界内存。泄漏(Leak)检测器仅检查您是否忘记了释放内存。
您可以在gcc 程序插桩选项页面阅读相关内容。
-fsanitize=address
启用AddressSanitizer,一种快速的内存错误检测工具。指令中添加仪表信息以检测越界和使用后释放的错误。该选项启用-fsanitize-address-use-after-scope
。更多详细信息请参见https://github.com/google/sanitizers/wiki/AddressSanitizer。运行时行为可以使用ASAN_OPTIONS
环境变量来影响。当设置为help=1
时,在插桩程序启动时会显示可用选项。有关支持的选项列表,请参见https://github.com/google/sanitizers/wiki/AddressSanitizerFlags#run-time-flags。此选项不能与-fsanitize=thread
组合使用。
-fsanitize=leak
启用LeakSanitizer,一种内存泄漏检测工具。此选项仅对可执行文件的链接有影响,并且该可执行文件链接到覆盖malloc和其他分配器函数的库。更多详细信息请参见https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer。运行时行为可以使用LSAN_OPTIONS
环境变量来影响。此选项不能与-fsanitize=thread
组合使用。
-fsanitize-address-use-after-scope
启用本地变量的消毒以检测使用后范围错误。该选项将-fstack-reuse
设置为none
。
-fstack-reuse=reuse-level
文档可以在代码生成选项页面中找到。
这个选项控制用户声明的本地/自动变量和编译器生成的临时变量的堆栈空间重用。reuse_level可以是'all'、'named_vars'或'none'。'all'启用所有本地变量和临时变量的堆栈重用,'named_vars'仅启用用户定义的具有名称的本地变量的重用,'none'完全禁用堆栈重用。默认值为“all”。当程序扩展了由语言定义的作用域局部变量或编译器生成的临时变量的生命周期时,需要该选项。当变量的生命周期结束,并且如果变量存在于内存中,则优化编译器可以自由地将其堆栈空间与其他临时变量或生命周期不重叠的作用域局部变量进行重用。延长局部生命周期的遗留代码可能会破坏堆栈重用优化。int *p;
{
int local1;
p = &local1;
local1 = 10;
....
}
{
int local2;
local2 = 20;
....
}
if (*p == 10) // out of scope use of local1
{
}
另一个例子:
struct A {
A(int k) : i(k), j(k) { }
int i;
int j;
};
A *ap;
void foo(const A& ar) {
ap = &ar;
}
void bar() {
foo(A(10)); // temp object's lifetime ends when foo returns
{
A a(20);
....
}
ap->i += 10; // ap references out of scope temp whose space
// is reused with a. What is the value of ap->i?
}
C++标准明确定义了编译器生成的临时对象的生命周期。当临时对象的生命周期结束,并且临时对象位于内存中时,优化编译器有权将其栈空间与其他生命周期不重叠的临时对象或局部变量的栈空间进行重用。然而,一些旧代码依赖于旧编译器的行为,这些编译器不会重新使用临时对象的栈空间,激进的栈重用可能导致运行时错误。此选项用于控制临时栈重用优化。
https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer
或者同样来自 LLVM:https://clang.llvm.org/docs/LeakSanitizer.html
但是使用--sanitize=leak运行似乎会使得通过LSAN_OPTION可用的不同选项,这些选项在运行--sanitize=address时不可用或被忽略。这是我通过将help=1运行到一个环境变量中发现的。