代码之家  ›  专栏  ›  技术社区  ›  Patrick Fromberg

来自未分配任何内容的程序的消毒程序的泄漏消息

  •  0
  • Patrick Fromberg  · 技术社区  · 1 年前

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

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

    但是,如果我替换的默认副本ctor arena_ptr 在手动实现的情况下,消毒程序将报告内存泄漏。 我可以在我的电脑上用不同版本的gcc和clang来复制这一点。我也可以在Godbold上用不同版本的gcc复制这一点,但不能用clang。 至关重要的是,如果不复制 竞技场_ptr 转换为lambda捕获(请参见函数 f 在下面我想了解这一点。这是我的代码:

    #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定义时的输出 竞技场_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).
    
    0 回复  |  直到 1 年前