我在项目中使用-fsanitize=leak
和-fsanitize=address
。我以为泄漏会发现内存泄漏(不删除内存),而地址会发现扭曲内存访问。但是地址也说明了未删除的内存。那么,出于什么目的-fsanitize=leak
是必需的?
答案 0 :(得分:5)
地址清理器会做很多额外的事情,例如检查是否正在写入超出范围的内存。泄漏清理器仅检查您是否忘记释放内存。
您可以在gcc program instrumentation options页上了解这些内容。
-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
文档可以在code gen options page上找到。
此选项控制用户声明的局部/自动变量和编译器生成的临时变量的堆栈空间重用。 redirect_level可以是“全部”,“ named_vars”或“无”。 “ all”启用所有局部变量和临时变量的堆栈重用,“ named_vars”仅启用具有名称的用户定义局部变量的重用,而“ none”则完全禁用堆栈重用。默认值为“全部”。当程序将作用域范围的局部变量的生存期延长到该语言所定义的端点之外,或者临时生成的编译器的寿命超出该语言定义的终点时,需要使用该选项。当变量的生存期结束时,并且如果该变量驻留在内存中,则优化编译器可以自由地将其堆栈空间与其他临时变量或作用域范围不重叠的局部作用域局部变量重用。延长本地生存期的旧代码可能会因堆栈重用优化而中断。
例如,
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 ++标准很好地定义了编译器生成的临时文件的生命周期。当临时变量的生存期结束时,并且如果该临时变量驻留在内存中,则优化编译器可以自由地将其堆栈空间与其他临时变量或作用域范围不重叠的局部作用域局部变量重用。但是,某些遗留代码依赖于较旧的编译器的行为,在这些行为中,临时器的堆栈空间未得到重用,激进的堆栈重用会导致运行时错误。此选项用于控制临时堆栈重用优化。
答案 1 :(得分:3)
为了查找内存泄漏,该工具需要查看您分配内存的所有位置,对其进行标记,跟踪它们的删除时间,并查看程序末尾是否有未删除的内容。
为了找到写访问冲突的内存,该工具(除其他事项外)需要查看分配内存的所有位置,对其进行标记,并跟踪它们的删除时间。这是必要的,因为它将使分配更大,以便可以在它们周围放置警惕以检测何时进行野写。
因此,跟踪内存泄漏所需的信息基本上90%可用于解决消毒问题。因此,它也可能会跟踪它们。
您不使用地址清理器来查找内存泄漏的原因是它执行了whole lot of other stuff。