C++ - 自定义智能指针集成 - shared_from_this() 不起作用

问题描述 投票:0回答:1

我正在使用这个库创建自定义智能指针,我可以在其中跟踪它们的堆栈调用和生命周期。

这是我的代码:

#ifndef VIBRANIUM_CORE_VEMEMORY_H
#define VIBRANIUM_CORE_VEMEMORY_H


#include <iostream>
#include <vector>
#include <ctime>

#define TRACK_SHARED_PTR_LEAKS 1

#if TRACK_SHARED_PTR_LEAKS
#define B_STACKTRACE_IMPL

#include <mutex>
#include <unordered_set>
#include <algorithm>
#include <iomanip>
#include <xmem/atomic_ref_count.hpp>
#include <xmem/common_control_block.hpp>
#include <xmem/ostream.hpp>
#include <xmem/basic_shared_from.hpp>
#include "xmem/shared_ptr.hpp"

class b_stacktrace_tag;
namespace VE {

    struct free_deleter {
        void operator()(void* ptr) { free(ptr); }
    };

    struct stacktrace {
        static constexpr bool init = true;
        stacktrace(bool init = false) {
            if (init) record();
        }
        xmem::unique_ptr<b_stacktrace_tag, free_deleter> m_trace;
        explicit operator bool() { return !!m_trace; }
        void record();
        friend std::ostream& operator<<(std::ostream& out, const stacktrace& st);
    };

    class MemoryControlBlock : protected xmem::control_block_base<xmem::atomic_ref_count> {
    public:
        using cb_type = MemoryControlBlock;
        struct entry {
            const void* ptr;
            stacktrace trace;
        };
    private:
        std::time_t m_creation_time;
        stacktrace m_creation_trace;
        mutable std::mutex m_mutex;
        std::vector<entry> m_active_strong;
    public:

        MemoryControlBlock()
                : m_creation_time(std::time(nullptr))
                , m_creation_trace(stacktrace::init)
        {}

        const time_t& creation_time() const { return m_creation_time; }
        const stacktrace& creation_trace() const { return m_creation_trace; }
        void log_active_strong(std::ostream& out) const {
            std::lock_guard _l(m_mutex);
            for (auto& ref : m_active_strong) {
                out << ref.ptr << ":\n";
                out << ref.trace << "\n";
            }
        }

        using super = xmem::control_block_base<xmem::atomic_ref_count>;

        void on_new_strong(const void* src) {
            std::lock_guard _l(m_mutex);
            auto& e = m_active_strong.emplace_back();
            e.ptr = src;
            e.trace.record();
        }

        void on_destroy_strong(const void* src) {
            std::lock_guard _l(m_mutex);
            auto f = std::find_if(m_active_strong.begin(), m_active_strong.end(), [&](const entry& e) { return e.ptr == src; });
            m_active_strong.erase(f);
        }

        void on_new_weak(const void* /*src*/) {
            // std::lock_guard _l(m_mutex);
        }

        void on_destroy_weak(const void* /*src*/) {
            // std::lock_guard _l(m_mutex);
        }

        void init_strong(const void* src) noexcept {
            super::init_strong(src);
            on_new_strong(src);
        }

        void inc_strong_ref(const void* src) noexcept {
            super::inc_strong_ref(src);
            on_new_strong(src);
        }
        void dec_strong_ref(const void* src) noexcept {
            on_destroy_strong(src);
            super::dec_strong_ref(src);
        }
        bool inc_strong_ref_nz(const void* src) noexcept {
            if (super::inc_strong_ref_nz(src)) {
                on_new_strong(src);
                return true;
            }
            return false;
        }
        using super::strong_ref_count;

        void transfer_strong(const void* dest, const void* src) {
            super::transfer_strong(dest, src);
            on_new_strong(dest);
            on_destroy_strong(src);
        }

        void inc_weak_ref(const void* src) noexcept {
            super::inc_weak_ref(src);
            on_new_weak(src);
        }
        void dec_weak_ref(const void* src) noexcept {
            on_destroy_weak(src);
            super::dec_weak_ref(src);
        }
        void transfer_weak(const void* dest, const void* src) {
            super::transfer_weak(dest, src);
            on_new_weak(dest);
            on_destroy_weak(src);
        }
    };

    using bookkeeping_control_block_factory = xmem::control_block_factory<MemoryControlBlock>;

    template <typename T>
    using shared_ptr = xmem::basic_shared_ptr<MemoryControlBlock, T>;

    template <typename T>
    using weak_ptr = xmem::basic_weak_ptr<MemoryControlBlock, T>;

    template <typename T>
    using enable_shared_from_this = xmem::basic_enable_shared_from_this<MemoryControlBlock, T>;


    template<class T, class U>
    shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept
    {
        auto p = static_cast<typename shared_ptr<T>::element_type*>(r.get());
        return shared_ptr<T>{r, p};
    }

    template <class T, class U>
    shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const& r) noexcept
    {
        if (auto p = dynamic_cast<typename shared_ptr<T>::element_type*>(r.get()))
            return shared_ptr<T>{r, p};
        else
            return shared_ptr<T>{};
    }

    template <typename T, typename... Args>
    [[nodiscard]] shared_ptr<T> make_shared(Args&&... args) {
        return shared_ptr<T>(bookkeeping_control_block_factory::make_resource_cb<T>(std::allocator<char>{}, std::forward<Args>(args)...));
    }




    template <typename T>
    [[nodiscard]] auto make_shared_ptr(T&& t) -> shared_ptr<std::remove_reference_t<T>>
    {
        return xmem::make_shared_ptr(t);
    }
}

#else

#include <memory>

namespace VE
{

using std::shared_ptr;
using std::weak_ptr;
using std::make_shared;
using std::enable_shared_from_this;
using std::static_pointer_cast;
using std::dynamic_pointer_cast;

}
#endif


#endif //VIBRANIUM_CORE_VEMEMORY_H

比我有这个代码:

#pragma once

#include "Memory/VEMemory.h"

template <class Base>
class enable_shared_from_base : public VE::enable_shared_from_this<Base>
{
protected:
    template <class Derived>
    VE::shared_ptr<Derived> shared_from_base()
    {
        return VE::static_pointer_cast<Derived>(this->shared_from_this());
    }
};

我创建了这个类:

namespace VE::Nodes {
class VENode : public enable_shared_from_base<VE::Nodes::VENode> {
        typedef std::set<VE::shared_ptr<VE::Components::VEComponent>> Components;
    
        friend class VE::Components::ComponentManager;
    
    public:
        explicit VENode(VEId veId);
    
        VENode(VENode const &ve_node, VEId veId);
    
        virtual ~VENode();
        virtual void Initialize();
        VE::shared_ptr<Transform> transform;
        void ComponentsPacket(packet_t& packet);
        void SetParent(VE::shared_ptr<VE::Nodes::VENode> parent)
        {
            parent_ = parent;
        }
        VE::shared_ptr<VE::Nodes::VENode> GetParent() { return parent_;}
    
    };
}

因此,我执行以下操作:

void VE::Nodes::VENode::Initialize()
{
    this->guid = VENodeManager->CreateGUID(id_.GetVEMask());
    try {
        auto node = shared_from_this();
        VENodeManager->AddNode(node);
    } catch (const std::bad_weak_ptr& e) {
        std::cerr << "Failed to obtain shared_ptr: " << e.what() << std::endl;
        // Additional handling or fallback
    }
}

在函数

Initalize()
中,
node
始终为空。这是为什么?

是否有任何指南或示例显示

shared_from_this
enable_shared_from_this
的用法?

c++
1个回答
0
投票

shared_from_this
的总体设计是
enable_shared_from_this
父类为自己存储一个
weak_ptr
。然后当你请求
shared_from_this
时,它实际上只是在
.lock()
上调用
weak_ptr

当您创建一个包装对象的共享指针时,

weak_ptr
就会被创建——无论是在
shared_ptr<T>(T*)
的构造函数中,还是在
make_shared_ptr
函数中。

基本上,如果您尚未在程序中的某个位置创建共享指针,则

shared_from_this
无法返回共享指针。

© www.soinside.com 2019 - 2024. All rights reserved.