我正在尝试学习如何使用
-fsanitize=address -fno-omit-frame-pointer
来检测内存泄漏。我写了一些简单的东西,显然有内存泄漏,但是用gcc -fsanitize=address -fno-omit-frame-pointer file.c
编译然后执行该函数似乎没有问题。
这篇文章似乎表明我们需要设置编译器标志和链接器标志,而不是使用
-lasan
如何在gcc中使用AddressSanitizer?。
我认为没有必要,但我已经尝试过
gcc -fsanitize=address -static-libasan -fno-omit-frame-pointer s.c
,因为文档似乎在这里提到了。 https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html
我也尝试了以下操作:https://lemire.me/blog/2016/04/20/no-more-leaks-with-sanitize-flags-in-gcc-and-clang/
以防万一,我使用的是 MacOS。我已经通过brew更新和升级了gcc。版本信息是:
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
这是我写的虚拟代码:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
char *buffer = malloc(1024);
sprintf(buffer, "%d", argc);
printf("%s\n", buffer);
buffer = malloc(10);
buffer[0] = 'A';
buffer[9] = '\0';
printf("%s\n", buffer);
}
我从未释放过任何东西,所以我希望地址清理程序能够捕获它。但是当我运行代码时,我得到以下结果:
$ ./s
1
A????????
我误解/做错了什么?
在带有 Apple Clang 的 macOS 上,
-fsanitize=address
默认情况下不一定能捕获内存泄漏。 AddressSanitizer
主要检测越界和释放后使用错误。 Apple 较旧的 Clang 工具链通常不完全支持内存泄漏检测组件(LeakSanitizer
或 LSan
)。
在许多基于 Linux/LLVM 安装中,
-fsanitize=address
还包括泄漏检测 if 您可以使用 ASAN_OPTIONS=detect_leaks=1
或使用 -fsanitize=leak
启用它。在装有 Apple Clang 的 macOS 上(尤其是 10.x、11.x 等旧版本),LeakSanitizer
通常被禁用或不完整。
但是,有一些解决方法。您可以从 Homebrew 安装 LLVM/Clang(不仅仅是 Apple 的 Xcode Clang)。
brew install llvm
/usr/local/opt/llvm/bin/clang -- version
然后尝试使用那个 clang 编译而不是 Apple 的编译。该版本具有更完整的 LSan/ASan 集成。
如果您的 Clang 环境支持,您可以设置环境变量来启用泄漏检测:
ASAN_OPTIONS=detect_leaks=1 ./s