【问题标题】:Undetected leak with asan and strsep()使用 asan 和 strsep() 未检测到泄漏
【发布时间】:2019-01-21 18:24:54
【问题描述】:

GCC 8.2.0 未检测到使用-fsanitize=address 编译的以下代码中的泄漏:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
        char *str1 = "tok1:val2";
        char *str1_dup = strndup(str1, strlen(str1));
        char *str1_dup_head = str1_dup;

        char *tok1 = strsep(&str1_dup, ":");

        // What should be done to avoid the memory leak
        //free(str1_dup_head);
        return 0;
}

但是,在以下情况下会检测到泄漏:

  • -fsanitize=leak编译
  • clang -fsanitize=address编译
  • 没有保留给strsep() (str1_dup_cpy) 的指针头部的副本时(参见下面的代码)
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

int main()
{
        char *str1 = "tok1:val2";
        char *str1_dup = strndup(str1, strlen(str1));
        //char *str1_dup_head = str1_dup;

        char *tok1 = strsep(&str1_dup, ":");

        // What should be done to avoid the memory leak
        //free(str1_dup_head);
        return 0;
}

知道为什么会出现这种行为吗?是否应该被-fsanitize=address检测到?

【问题讨论】:

  • strndup 为复制的字符分配存储空间。
  • @Barmar 否,因为 strsep() 移动了指针。见这里stackoverflow.com/questions/21000218/…。还有人 strsep。
  • @JeffBencteux 谢谢,没有看到那里正在使用该变量。

标签: c gcc address-sanitizer


【解决方案1】:

LeakSanitizer 在设计上使用了一种非常原始的泄漏检测算法。每当对已分配块的引用碰巧位于堆栈、寄存器或活动堆块的某个位置时,LSan 都会认为它是“可访问的”,因此不会报告泄漏。这使得它对编译器版本、优化选项(即变量是否溢出到堆栈)等非常敏感。我强烈怀疑你遇到了这个限制。

【讨论】:

  • 你知道为什么将 LeakSanitizer 与 -fsanitize=leak 一起使用会得到与使用 -fsanitize=address 隐式启用不同的结果吗?
  • @JeffBencteux 仔细检查一下,export ASAN_OPTIONS=detect_leaks=1 有什么改变吗?
  • 不,与上述环境变量结果相同。
猜你喜欢
  • 2023-01-29
  • 2012-07-16
  • 1970-01-01
  • 1970-01-01
  • 2015-08-21
  • 1970-01-01
  • 1970-01-01
  • 2020-08-05
  • 1970-01-01
相关资源
最近更新 更多