簡體   English   中英

使用 shared_from_this 時出現“std::bad_weak_ptr”錯誤

[英]'std::bad_weak_ptr' error while using shared_from_this

注意:在發布問題之前,我在使用shared_from_this將現有 shared_ptr 實例的 shared_ptr 傳遞給另一個方法時,已經完成了關於 std::bad_weak_error 的現有問題。 它們都不像這樣:

  • 在嘗試調用 shared_from_this shared_from_this()之前,已經創建了 class 的現有 shared_ptr 實例
  • class 公開繼承自 std::enable_shared_from_this<>。

以下是重現錯誤的示例代碼:


#include <iostream>
#include <memory>

class ILogger {
public:
    virtual ~ILogger() {}

    virtual void Log() = 0;
};

class LogManager;

class Logger : public ILogger {
public:
    Logger(std::shared_ptr<LogManager> logManager)
        : m_logManager(logManager)
    {
    }

    void Log() override
    {
        std::cout << "Dump logs";
    }

private:
    std::shared_ptr<LogManager> m_logManager;
};

class ILogManager {
public:
    virtual ~ILogManager() {}

    virtual std::shared_ptr<ILogger> GetLogger() = 0;
};

class LogManager : public ILogManager, public std::enable_shared_from_this<LogManager> {
public:
    virtual std::shared_ptr<ILogger> GetLogger()
    {
        return std::static_pointer_cast<ILogger>(std::make_shared<Logger>(this->shared_from_this()));
    }
};

class LogManagerFactory {
public:
    static ILogManager* Create()
    {
        auto logManager = new LogManager();
        return logManager;
    }
};

int main()
{
    auto logManager = std::shared_ptr<ILogManager>(LogManagerFactory::Create());
    auto logger = logManager->GetLogger();
}

錯誤:

Program returned: 139
terminate called after throwing an instance of 'std::bad_weak_ptr'
  what():  bad_weak_ptr

代碼鏈接: https://godbolt.org/z/GTcafM449

為了初始化enable_shared_from_this子對象, shared_ptr構造函數需要知道所討論的 class 繼承自enable_shared_from_this 查看創建共享指針的表達式:

std::shared_ptr<ILogManager>(LogManagerFactory::Create());

該表達式中唯一涉及的 class並未繼承自std::enable_shared_from_this<> 您正在從指向ILogManager的指針創建指向ILogManager的共享指針。 這就是編譯器生成代碼的目的——為不從enable_shared_from_this繼承的 class 創建一個shared_ptr 構造函數不知道您期望它初始化enable_shared_from_this子對象。

如果您將LogManagerFactory::Create()的返回類型從ILogManager*更改為LogManager* ,則該代碼有效。 只要構造參數將LogManager引入圖片,您就可以保留std::shared_ptr<ILogManager>部分。

注意:為了更安全, LogManagerFactory::Create()應該返回unique_ptrshared_ptr而不是原始指針,以清楚地表明調用者獲得了所有權。

當你運行時:

std::shared_ptr<ILogManager>(LogManagerFactory::Create())

shared_ptr只知道指針是一個沒有ILogManagerenable_shared_from_this ,所以不設置弱指針。

解決方案(通常是更安全的代碼)是在Create中創建shared_ptr ,此時構造函數可以看到真實類型,因此enable_shared_from_this將起作用:

    static std::shared_ptr<ILogManager> Create()
    {
        auto logManager = new LogManager();
        return std::shared_ptr<ILogManager>(logManager);
    }

或者更簡單地說:

    static std::shared_ptr<ILogManager> Create()
    {
        return std::make_shared<LogManager>();
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM