为啥 LLVM 的泄漏消毒剂在与其他启用的消毒剂一起使用时不起作用

Posted

技术标签:

【中文标题】为啥 LLVM 的泄漏消毒剂在与其他启用的消毒剂一起使用时不起作用【英文标题】:Why LLVM's leak sanitizer not working when using with other sanitizers enabled为什么 LLVM 的泄漏消毒剂在与其他启用的消毒剂一起使用时不起作用 【发布时间】:2022-01-16 04:59:54 【问题描述】:

我试图从一个简单的程序中找到内存泄漏:

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

void parse(const char* input) 
    // Goal: parse out a string between brackets
    // (e.g. "   [target string]" -> "target string")

    char *mutable_copy = strdup(input);

    // Find open bracket
    char *open_bracket = strchr(mutable_copy, '[');
    if (open_bracket == NULL) 
        printf("Malformed input!\n");
        free(mutable_copy);
        return;
    

    // Make the output string start after the open bracket
    char *parsed = open_bracket + 1;

    // Make sure there is at least one character in brackets
    if (parsed[0] == '\0') 
        printf("There should be at least one character in brackets!\n");
        free(mutable_copy);
        return;
    

    // Find the close bracket
    char *close_bracket = strchr(parsed, ']');
    if (close_bracket == NULL) 
        printf("Malformed input!\n");
        return;
    

    // Replace the close bracket with a null terminator to end the parsed
    // string there
    *close_bracket = '\0';

    printf("Parsed string: %s\n", parsed);
    free(mutable_copy);


int main(int argc, char *argv[]) 
    if (argc < 2) 
        printf("Usage: %s <string to parse>\n", argv[0]);
        return 1;
    

    parse(argv[1]);

    return 0;

使用以下命令: clang -g -O0 -Wall -Wextra -std=gnu99 -fsanitize=address,leak -o 3-bracket-parser 3-bracket-parser.c

很明显,在这个程序中,如果close_bracket == NULL为真,那么程序返回时没有空闲的mutable_copy,所以存在内存泄漏。

但是,当我运行此命令时,它不会报告任何错误,并且我的 sanitizer 也没有输出。我只启用了泄漏消毒剂再次尝试,这次成功了:

=================================================================
==19699==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 17 byte(s) in 1 object(s) allocated from:
    #0 0x10f77ab48 in wrap_malloc+0x58 (libclang_rt.lsan_osx_dynamic.dylib:x86_64h+0x9b48)
    #1 0x7fff202b88d1 in strdup+0x1f (libsystem_c.dylib:x86_64+0x578d1)
    #2 0x10f763db4 in parse 3-bracket-parser.c:10
    #3 0x10f763edd in main 3-bracket-parser.c:51
    #4 0x7fff203a7f3c in start+0x0 (libdyld.dylib:x86_64+0x15f3c)

SUMMARY: LeakSanitizer: 17 byte(s) leaked in 1 allocation(s).

我想知道为什么在启用其他消毒剂时泄漏消毒剂不起作用。

我的 clang 版本是 Homebrew clang 版本 12.0.1,我的操作系统是 macOS Big Sur 11.5.2

【问题讨论】:

【参考方案1】:

问题解决了。事实证明,在 OS X 上,lsan 是集成到 asan 中的,使用 asan 时必须手动使用 ASAN_OPTIONS=detect_leak=1 来启用 lsan。似乎如果使用 -fsanitize=address,leak,clang 认为这个泄漏参数是多余的,因为地址清理程序已经包含泄漏清理程序。如果仔细查看链接命令,您可能会发现 ld 仅在启用两个 sanitizer 时才链接 asan dylib,并且您需要添加 ASAN_OPTIONS 以启用 lsan。但是,如果您单独使用泄漏清理器,则无需使用 ASAN_OPTIONS 来指定您也希望启用 lsan,并且 lsan 可以正常工作。

【讨论】:

以上是关于为啥 LLVM 的泄漏消毒剂在与其他启用的消毒剂一起使用时不起作用的主要内容,如果未能解决你的问题,请参考以下文章

MSVC 中的地址消毒器:为啥它在启动时报告错误?

基于物联网设计的自反馈深紫外杀菌消毒系统(STM32F407)

基于物联网设计的自反馈深紫外杀菌消毒系统(STM32F407)

紫外线/烘箱消毒后 口罩能反复使用

[HNOI2001]软件开发

<span style=...> 消毒是不是安全?