Завершить вызов после создания экземпляра 'std::bad_weak_ptr'

У меня 2 класса. Я хочу передать this из конструктора одного класса в качестве параметра в конструктор другого класса.

Я знаю, что ошибка произошла из-за того, что функция Shared_from_this() вызывается до того, как объект IkArm (this) будет полностью создан. Но я не могу найти способ передать узел второму классу после выполнения первого класса. Также я рассмотрел этот вопрос, но соотношение используемых там классов другое.

Ниже приведен код:

#include "rclcpp/rclcpp.hpp"

class IkSolver
{
    public:
        IkSolver(std::shared_ptr<rclcpp::Node> node) : node_(node)
        {
            RCLCPP_INFO(node_->get_logger(), "2nd Constructor");                
        }

    private:
        std::shared_ptr<rclcpp::Node> node_;
};

class IkArm : public rclcpp::Node
{
    public:
        IkArm() : Node("IkNode")
        {
            RCLCPP_INFO(this->get_logger(), "1st Constructor");
            
            obj1_ = std::make_shared<IkSolver>(shared_from_this());
            RCLCPP_INFO(this->get_logger(), "Back To 1st Constructor");
        }

    private:
        std::shared_ptr<IkSolver> obj1_;
};


int main(int argc, char * argv[])
{
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<IkArm>());
    rclcpp::shutdown();
    return 0;
}

Я получаю следующую ошибку:

[INFO] [1720452645.004303274] [IkNode]: 1st Constructor
terminate called after throwing an instance of 'std::bad_weak_ptr'
  what():  bad_weak_ptr
[ros2run]: Aborted

РЕДАКТИРОВАТЬ_1: После внесения изменений, предложенных @Ahmed AEK, возникает следующая ошибка:

error: could not convert ‘std::enable_shared_from_this<_Tp>::shared_from_this() [with _Tp = rclcpp::Node]()’ from ‘shared_ptr<rclcpp::Node>’ to ‘shared_ptr<IkArm>’
   32 |             return shared_from_this();
      |                    ~~~~~~~~~~~~~~~~^~
      |                                    |
      |                                    shared_ptr<rclcpp::Node>

Обновленный код:

#include "rclcpp/rclcpp.hpp"

class IkSolver
{
    public:
        IkSolver(std::shared_ptr<rclcpp::Node> node) : node_(node)
        {
            RCLCPP_INFO(node_->get_logger(), "2nd Constructor");                
        }

    private:
        std::shared_ptr<rclcpp::Node> node_;
};

class IkArm : public rclcpp::Node
{
    public:
        IkArm() : Node("IkNode")
        {
            RCLCPP_INFO(this->get_logger(), "1st Constructor");
            
            RCLCPP_INFO(this->get_logger(), "Back To 1st Constructor");
        }

        std::shared_ptr<IkArm> init()
        {
            obj1_ = std::make_shared<IkSolver>(shared_from_this());
            return shared_from_this();
        }

    private:    
        std::shared_ptr<IkSolver> obj1_;
};


int main(int argc, char * argv[])
{
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<IkArm>()->init());
    rclcpp::shutdown();
    return 0;
}

Вы просто не можете использовать shared_from_this внутри конструктора. Обычно я думаю о том, как изменить API, обычно с помощью фабричной функции для создания объекта, а затем что-то сделать с shared_ptr, или путем адаптации логики и «кто что делает» для размещения shared_from_this.

Christian Stieber 08.07.2024 18:59

Несколько не связано с рассматриваемым вопросом, но учтите, что если вы не предпримете дополнительные шаги для предотвращения этого (которые не показаны), ваш текущий код приведет к утечке памяти, поскольку IkArm владеет IkSolver, который, в свою очередь, владеет IkArm. Ни один из счетчиков ссылок shared_ptr никогда не достигнет 0 (и, следовательно, ни один объект никогда не будет удален), пока у вас есть этот цикл в вашем графе владения. std::weak_ptr может помочь в решении этой проблемы.

Miles Budnek 08.07.2024 19:55
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
85
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не можете вызвать shared_from_this из конструктора, вы можете вызывать shared_from_this только для объектов, которые уже привязаны к shared_ptr, тогда как std::make_shared привязывает объект к shared_ptr после того, как его конструктор завершен.

из std::enable_shared_from_this

Разрешено вызыватьshared_from_this только на ранее опубликованном объект, то есть объект, управляемый std::shared_ptr. В противном случае, std::bad_weak_ptr выбрасывается (конструкторомshared_ptr из созданный по умолчанию слабый-это).

вам нужно поместить конструкцию члена в другую функцию-член, которую вы вызываете вне конструктора.

rclcpp::spin(std::make_shared<IkArm>()->init());

// init implemenation
std::shared_ptr<rclcpp::Node> IkArm::init()
{
    obj1_ = std::make_shared<IkSolver>(shared_from_this());
    return shared_from_this();
}

Также обратите внимание, что у вас есть циклическая ссылка , внутри члена следует хранить только weak_ptr, а не shared_ptr, иначе ни один из двух объектов не будет удален.

Спасибо за ответ. Но я получаю еще одну ошибку. Обновил вопрос.

Pratham 09.07.2024 11:04

@Pratham, просто вместо этого введите возвращаемый тип std::shared_ptr<rclcpp::Node>.

Ahmed AEK 09.07.2024 11:06

Спасибо. Проблема решена. Для информации: работали ли вы ранее с библиотекой rclcpp (связанной с Robotics ROS2)?

Pratham 09.07.2024 12:26

Другие вопросы по теме