未分配任何内容的程序的清理程序泄漏消息

Leakage message from sanitizer for program that does not allocate anything

提问人:Patrick Fromberg 提问时间:7/22/2023 最后编辑:Patrick Fromberg 更新时间:7/22/2023 访问量:40

问:

我有一些代码几乎什么都不做,但它以一种复杂的方式这样做。最重要的是,它不分配任何东西。所有数据都在堆栈上。它适用于许多版本的 gcc 和 clang,无论是在我的计算机上还是在 Godbolds 编译器资源管理器中。我是否使用 或 编译并不重要。这就是我的编译方式。-std=20-std=17

g++  -std=c++17  -g -O0  -fsanitize=address -fno-omit-frame-pointer  leaking_memory.cpp 

但是,如果我用手动实现替换默认的副本 ctor,那么清理程序将报告内存泄漏。 我可以在我的计算机上使用不同版本的 gcc 和 clang 重现这一点。我也可以在 Godbold 上使用不同版本的 gcc 重现这一点,但不能重现 clang。 至关重要的是,如果不将 复制到 lambda 捕获中,我无法重现此错误(请参阅下面的函数)。这是我想理解的。这是我的代码:arena_ptrarena_ptrf

#include <memory>
#include <memory_resource>
#include <functional>

struct arena {
    alignas(64) std::byte memory_[1000000] = {std::byte{}};
    std::byte *pos_ = memory_;
    template<typename T, typename... Args>
    T *new_object(Args &&...args) {
        auto *ptr = new (pos_) T(std::forward<Args>(args)...);
        pos_ += sizeof(T) + (size_t(pos_) % 8UL);
        return ptr;
    }
};

arena * a_ptr = nullptr;

template<typename T>
struct arena_ptr {
    T *value_ptr_ = nullptr;
    explicit arena_ptr(T *value_ptr_) : value_ptr_(value_ptr_) {}
    arena_ptr() = delete;
    arena_ptr(arena_ptr const &) = default;
    //inline arena_ptr(arena_ptr const &other) : value_ptr_(other.value_ptr_) {}
    arena_ptr(arena_ptr &&) = delete;
    arena_ptr &operator=(arena_ptr const &) = delete;
    arena_ptr &operator=(arena_ptr &&) = delete;
    ~arena_ptr() = default;
};

template<typename T, typename... Args>
arena_ptr<T> make_arena_ptr(Args &&...args) {
    T *ptr = a_ptr->new_object<T>(std::forward<Args>(args)...);
    return arena_ptr(ptr);
}

struct TT {};

struct CC {
    using PP = std::function<bool()>;
    PP pp;
    CC(CC const &) = default;
    explicit CC(PP pp) : pp(std::move(pp)) {}
};

auto f(arena_ptr<TT> left) {
    auto f = [left]() { return true; };
    return make_arena_ptr<CC>(f);
}

auto g() {
    auto int_number = []() { return make_arena_ptr<TT>(); };
    return f(int_number());
}

int main() {
    arena a;
    a_ptr = &a;
    auto program = g();
}

这是我使用手动 ctor 定义时的输出:arena_ptr

=================================================================
==1==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 8 byte(s) in 1 object(s) allocated from:
    #0 0x7f2af4f9c528 in operator new(unsigned long) (/opt/compiler-explorer/gcc-13.1.0/lib64/libasan.so.8+0xdb528) (BuildId: c9b24be17e4cbd04bdb4891782c4425e47a9259a)
    #1 0x401b44 in _M_create<f(arena_ptr<TT>)::<lambda()>&> /opt/compiler-explorer/gcc-13.1.0/include/c++/13.1.0/bits/std_function.h:161
    #2 0x401a25 in _M_init_functor<f(arena_ptr<TT>)::<lambda()>&> /opt/compiler-explorer/gcc-13.1.0/include/c++/13.1.0/bits/std_function.h:215
    #3 0x401961 in function<f(arena_ptr<TT>)::<lambda()>&> /opt/compiler-explorer/gcc-13.1.0/include/c++/13.1.0/bits/std_function.h:449
    #4 0x40172f in new_object<CC, f(arena_ptr<TT>)::<lambda()>&> /app/example.cpp:10
    #5 0x401607 in make_arena_ptr<CC, f(arena_ptr<TT>)::<lambda()>&> /app/example.cpp:35
    #6 0x4012f1 in f(arena_ptr<TT>) /app/example.cpp:54
    #7 0x401467 in g() /app/example.cpp:59
    #8 0x4015a8 in main /app/example.cpp:65
    #9 0x7f2af491a082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 1878e6b475720c7c51969e69ab2d276fae6d1dee)

SUMMARY: AddressSanitizer: 8 byte(s) leaked in 1 allocation(s).
C++ 分配器 放置 - 新 清理剂

评论

1赞 Sam Varshavchik 7/22/2023
std::function<bool()>;在内部进行动态分配。显示的代码非常复杂,但我怀疑它正在构造一个实例,但没有正式销毁它,从而泄漏内存。std::function
0赞 Sam Varshavchik 7/22/2023
是的,我在堆栈跟踪中看到了对的调用。这就是正在发生的事情。除了执行 placement-new 之外,您还需要放置销毁。make_arena_ptr
0赞 Patrick Fromberg 7/22/2023
@SamVarshavchik,你是完全正确的。 分配是因为它捕获了超过 16 个字节。但是,无论默认副本是默认的还是由用户定义的,消毒器都应该抱怨。std::functionarena_ptr
0赞 Sam Varshavchik 7/22/2023
我想这取决于默认的做什么,而不是用户定义的。
0赞 Patrick Fromberg 7/22/2023
@SamVarshavchik,用户定义的一个在默认的下方注释。我以为是一样的。

答: 暂无答案