2

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

#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,所以存在内存泄漏。

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

=================================================================
==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

4

1 回答 1

0

问题解决了。事实证明,在 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 可以正常工作。

于 2021-12-14T08:11:40.957 回答