使用Instruments检测C / C ++命令行内存泄漏

问题描述 投票:2回答:1

我正在尝试检测macOS上C(和C ++)程序中的内存泄漏。在Linux和Windows中,我可以使用valgrind轻松地做到这一点,但是不幸的是,它在macOS上不可用。

[由于我具有ObjC和iOS开发人员的背景经验,因此我考虑使用Instruments进行内存泄漏检查。乍一看,听起来很完美。

我写了这个[[very简单的泄漏程序:

#include <stdlib.h> #include <stdio.h> int* allocSomething() { return malloc(sizeof(int)); } int main(int argc, const char * argv[]) { int* p = allocSomething(); *p = 5; printf("*p = %d\n", *p); p = NULL; return 0; }
我通过执行此任务的Clang静态分析器运行它,但是我也希望它也能被Instruments捕获,因为我正在寻找合适的Valgrind替代品。因此:

    我将Profile模式更改为使用Debug而不是Release。
  • 我确保没有优化。
  • 但是,使用乐器后:Instruments does not detect leaks

    您可以看到,没有泄漏报告。在网上搜索后,我遇到了Can't detect C leaks in xcode 9 instruments,作者使用了sleep,所以我认为Instruments实际上并没有以Valgrind的身份覆盖malloc,而是使用了采样技术,并且没有对它进行采样这么短的通知,所以我将程序更改为:

    int main(int argc, const char * argv[]) { int* p = allocSomething(); p = NULL; sleep(600000); return 0; }

    现在,我得到:no leak at all

    这完全没有意义,因为这是明显的内存泄漏。我会说它必须做一些优化,但随后我又明确禁用了它。另外,如果我再malloc个字节,它会检测到它。也许这是Instruments中的错误?

    所以,我想知道这是否是无法检测少量分配的文书问题?我必须指出,Valgrind可以很好地处理它,因此我感到惊讶。

    您有任何建议吗?

  • c xcode memory-leaks valgrind xcode-instruments
    1个回答
    2
    投票
    [Leaks工具(Leaks模板中的工具之一)的工作方式与您期望的不同。

    首先,为什么对于短暂的进程它什么也没检测到:它是基于计时器的。它会经常停止该过程,并检查是否有泄漏。对于短暂的流程,检查永远不会在流程退出之前进行。

    其次,为什么它会遗漏一些泄漏:它检查所有线程的堆栈,所有线程的寄存器以及寻找分配地址的全局变量。如果在任何这些地方都找到了分配的地址,则认为该分配没有泄漏。

    在您的情况下,分配的地址可能仍在寄存器或堆栈存储器中。在“真实”程序中,堆栈和寄存器最终将被重用,并且这些陈旧的数据将被消除。

    分配工具确实会跟踪所有分配和取消分配(假设该过程由Instruments启动)。您泄漏的分配位于分配列表中,并且仍列为“实时”(又称“已创建”和“永久”)。问题在于分配工具没有明确调用诸如泄漏之类的分配。

    此外,系统库还进行了分配,这些分配旨在保留到进程退出之前,并且不会显式清除。因此,您的泄漏被隐藏在无关的信息中。您可以对分配列表进行过滤和排序以发现您的泄漏,但是需要做一些事情。

    在更真实的程序中,Instruments非常擅长于发现泄漏。

    显然,Clang支持LeakSanitizer,它可以作为AddressSanitizer的一部分,也可以独立使用。这可能需要比苹果作为Xcode和/或Catalina附带的版本更高的Clang版本。 (我在Mojave上使用Xcode 11.3.1进行了测试。它不支持-fsanitize=leak选项,也不支持ASAN_OPTIONS=detect_leaks=1。)假设您可以使用它,那么它的行为可能会更像您期望的那样。

    © www.soinside.com 2019 - 2024. All rights reserved.