【问题标题】:Initializing an object in a class constructor在类构造函数中初始化对象
【发布时间】:2021-11-06 02:54:34
【问题描述】:

存在运行时错误:

在抛出 'std::bad_alloc' 实例后调用终止
what(): std::bad_alloc 中止(核心转储)

来自下面的 c++ 类:

class PoseDrawer
{
public:
  PoseDrawer() : tf_(),  target_frame_("turtle1"), tf_filter_(point_sub_, tf_, target_frame_, 10)
  {
    point_sub_.subscribe(n_, "turtle_point_stamped", 10);
    tf_filter_.registerCallback( &PoseDrawer::msgCallback, this );
  } ;


private:
  message_filters::Subscriber<geometry_msgs::PointStamped> point_sub_;
  tf::TransformListener tf_;
  tf::MessageFilter<geometry_msgs::PointStamped> tf_filter_;
  ros::NodeHandle n_;
  std::string target_frame_;

  void msgCallback(const boost::shared_ptr<const geometry_msgs::PointStamped>& point_ptr) 
  {
  //stuff
  }
};

这是由于tf_filter_ 的初始化方式,因为如果我将tf_filter_ 转换为如下指针,它将按预期工作。那么上面的代码和下面的代码有什么区别呢?

class PoseDrawer
{
public:
  PoseDrawer() : tf_(),  target_frame_("turtle1")
  {
    point_sub_.subscribe(n_, "turtle_point_stamped", 10);
    tf_filter_=new tf::MessageFilter<geometry_msgs::PointStamped>(point_sub_, tf_, target_frame_, 10);
    tf_filter_->registerCallback( &PoseDrawer::msgCallback, this );
  } ;


private:
  message_filters::Subscriber<geometry_msgs::PointStamped> point_sub_;
  tf::TransformListener tf_;
  tf::MessageFilter<geometry_msgs::PointStamped>* tf_filter_;
  ros::NodeHandle n_;
  std::string target_frame_;

  void msgCallback(const boost::shared_ptr<const geometry_msgs::PointStamped>& point_ptr) 
  {
   //stuff
  };

};

【问题讨论】:

  • 已尝试附加调试器?你知道它在哪一行失败了吗?
  • std::bad_alloc 通常意味着您的内存已用完。我们这里没有足够的信息来诊断问题。可以发minimal reproducible example吗?
  • 当您在自己的构造函数中直接实例化一个对象时,或者当该对象在构造函数中实例化的其他对象的其他构造函数中实例化该对象时,可能会发生这种情况。这会导致构造函数的直接或间接递归。
  • 我在问题中编辑并添加了工作代码。问题显然源于 tf_filter_ 在类中的实例化方式。
  • 我从死容器上调用函数得到了std::bad_allocs。将tf_filter_ 移动到动态内存并泄漏它的方式使我认为您的PoseDrawer 实例在某些时候被意外破坏,其他一些代码仍然引用它现在已死的tf_filter_ 并稍后访问它。不过,这只是一个有根据的猜测——使用调试器准确找出引发此异常的代码会有很大帮助。

标签: c++ class constructor


【解决方案1】:

在类中,您在 tf_filter_ 之后声明 target_frame_,但您在 tf_filter_ 构造函数中使用它。你应该得到关于那个的警告。这是您正在做的事情的提炼示例:

#include <string>

class PoseDrawer
{
public:
  PoseDrawer() : target_frame_("turtle1"), tf_filter_(target_frame_)
  {
  } 

private:
  std::string tf_filter_;
  std::string target_frame_;
};

godbolt

<source>: In constructor 'PoseDrawer::PoseDrawer()':
<source>:12:15: warning: 'PoseDrawer::target_frame_' will be initialized after [-Wreorder]
   12 |   std::string target_frame_;
      |               ^~~~~~~~~~~~~
<source>:11:15: warning:   'std::string PoseDrawer::tf_filter_' [-Wreorder]
   11 |   std::string tf_filter_;
      |               ^~~~~~~~~~
<source>:6:3: warning:   when initialized here [-Wreorder]
    6 |   PoseDrawer() : target_frame_("turtle1"), tf_filter_(target_frame_)
      |   ^~~~~~~~~~

target_frame_ 声明移到tf_filter_ 之前,看看是否有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-30
    • 1970-01-01
    • 2021-09-10
    • 2016-01-08
    • 1970-01-01
    • 1970-01-01
    • 2012-03-05
    相关资源
    最近更新 更多