You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ROS订阅者使用回调数据触发boost断言错误求助

解决ROS订阅者回调空指针断言错误(保留ConstPtr)

你遇到的boost::shared_ptr断言失败错误,核心原因是订阅者启动初期还未收到任何消息时,Listener类的data成员是空指针,直接调用->访问其成员会触发C++的空指针断言,导致程序崩溃。以下是几种保留ConstPtr(避免消息拷贝)的解决方案:

方案1:访问前检查指针有效性

在主循环中先判断data是否非空,再进行访问,这是最简单直接的处理方式:

while(ros::ok())
{
  if (listener.data) {
    std::cout << " Data is " << listener.data->data.c_str() << std::endl;
  } else {
    std::cout << "Waiting for incoming messages..." << std::endl;
  }
  ros::spinOnce();
  loop_rate.sleep();
}

这种方式会在收到消息前输出等待提示,收到消息后正常打印内容,完全保留ConstPtr的无拷贝特性。

方案2:初始化空消息指针

在Listener类的构造函数中,初始化data为一个指向空std_msgs::String对象的ConstPtr,这样即使没有收到外部消息,指针也不是空的,访问不会触发断言:

class Listener
{
public:
  std_msgs::String::ConstPtr data;
  // 初始化指向空消息的智能指针
  Listener() : data(std::make_shared<const std_msgs::String>()) {}
  void callback(const std_msgs::String::ConstPtr& msg);
};

void Listener::callback(const std_msgs::String::ConstPtr& msg) 
{ 
  data = msg; 
}

主循环无需修改,未收到消息时会输出空字符串,收到消息后自动覆盖为最新内容。

方案3:用条件变量等待首个消息(线程安全版)

如果希望程序在收到第一个消息后才开始输出,同时避免回调与主循环的竞态问题,可以使用条件变量同步:

#include <condition_variable>
#include <mutex>

class Listener
{
public:
  std_msgs::String::ConstPtr data;
  std::mutex mtx;
  std::condition_variable cv;
  bool has_received_msg = false;

  void callback(const std_msgs::String::ConstPtr& msg);
};

void Listener::callback(const std_msgs::String::ConstPtr& msg) 
{ 
  std::lock_guard<std::mutex> lock(mtx);
  data = msg; 
  has_received_msg = true;
  cv.notify_one();
}

int main(int argc, char **argv)
{ 
  Listener listener;
  ros::init(argc, argv, "listener_class");
  ros::NodeHandle n;

  ros::Subscriber sub = n.subscribe("chatter", 1000, &Listener::callback, &listener);

  // 阻塞等待第一个消息
  std::unique_lock<std::mutex> lock(listener.mtx);
  listener.cv.wait(lock, [&listener]{ return listener.has_received_msg; });

  ros::Rate loop_rate(1);
  while(ros::ok())
  {
    std::lock_guard<std::mutex> lock(listener.mtx);
    std::cout << " Data is " << listener.data->data.c_str() << std::endl;
    ros::spinOnce();
    loop_rate.sleep();
  }

  return 0;
}

这种方式不仅解决了空指针问题,还通过互斥锁保证了多线程环境下数据访问的安全性,同时完全保留ConstPtr的无拷贝优势。

内容的提问来源于stack exchange,提问作者Ankit Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 18:57:05