首页 > 解决方案 > 将结构插入地图时出现分段错误

问题描述

被填充的mapBase参数将代表一个坐标系。我使用std::map基于 x 轻松排序坐标,然后配对到由内部地图排序的 y 坐标。内部映射的值稍后将保存额外的信息。现在它填充了虚拟数据。

我正在尝试将结构插入 a std::map,但插入时出现段错误。段错误并不总是一致的。有时插入会工作多次,然后在没有特定的时间后出现段错误。

std::map::insert我尝试添加调试语句,通过使用函数的结果并查看结果的第二个字段来告诉我何时成功插入某些内容。这仅在没有发生段错误时才有用,并且通常总是正确的,因为我mapBase在被调用函数的开头清除了。我还尝试使用智能共享指针作为最终值类型,baseMap而不仅仅是结构对象本身。这并没有改变我的结果。我也尝试分配*(new cell())相同的结果。我在下面提供了基本代码。

主要的:

    #include <map>
    #include <cmath>
    #define DEG_TO_RAD(deg) deg * M_PI / 180

    int main(int argc, char **argv)
    {
      // vector of lidar range, angle pairs
      std::vector<std::pair<double, double>> lidarData {{0.585, -179.41},
                                                        {0.689, -151.672},
                                                        {0.671, 56.6557},
                                                        {0.717, 122.164},
                                                        {0.611, 159.344},
                                                        {0.586, 175.279}};
    
      // convert returns to x, y coordinate point
      std::vector<Eigen::Matrix<double, 2, 1>> points;
      for(const auto& beam : lidarData)
      {
        double angle = DEG_TO_RAD(beam.second);
        double range = beam.first;
        double x = range * cos(angle); // r * cos(theta)
        double y = range * sin(angle); // r * sin(theta)
        Eigen::Matrix<double, 2, 1> point;
        point << x, y;
        points.emplace_back(point);
      }
    
      auto* newA = new A();
      newA->doSomething(points);
      
      return 0;
    }

标题:

class A {
    public:
        A();

        ~A();
  
        void doSomething(std::vector<Eigen::Matrix<double, 2, 1>> &points);
  
    private:
        struct cell {
            Eigen::Matrix<double, 2, 1> mean;
            Eigen::Matrix<double, 2, 2> covariance;
            std::vector<double> x_m {};
            std::vector<double> y_m {};
            std::vector<Eigen::Matrix<double, 2, 1>> hits {};

            cell();
        };

        // define a map keyed by a x coordinate with a value of  std::map.
        // inner map is keyed by a y coordinate with a value of struct type cell.
        typedef std::map<double, std::map<double, cell>> map;
        map mapBase;
    }
}

来源

A::A() {}

A::~A() {}

void A::doSomething(std::vector<Eigen::Matrix<double, 2, 1>> &points) {
    mapBase.clear();
    for (const auto &point : points) {
        auto x = point.x();
        auto y = point.y();

        auto xIt = mapBase.find(x);
        if (xIt == mapBase.end()) { // coordinate does not exist if true
            std::map<double , cell> yPair;
            yPair.insert(std::make_pair(y, cell()));  // Segfault happens here
            mapBase.insert(std::make_pair(x, yPair));
        } else { // x exist in map, but check if y does
            auto yIt = mapBase.at(x).find(y);
            if (yIt == mapBase.at(x).end()) { // y does not exist at x if true
                mapBase.at(x).insert(std::make_pair(y, cell()));
            }
        }

        // Emplace values at the new cell in the map. 
        mapBase.at(x).at(y).x_m.emplace_back(x);
        mapBase.at(x).at(y).y_m.emplace_back(y);
        mapBase.at(x).at(y).hits.emplace_back(Eigen::Matrix<double, 2, 1>());
        mapBase.at(x).at(y).mean.setOnes();
        mapBase.at(x).at(y).covariance.setOnes();
    }
};

A::cell::cell() {
    mean.setZero();
    covariance.setOnes();
    x_m.clear();
    y_m.clear();
    hits.clear();
}

在定期执行代码时,我只是在插入结构时遇到分段错误(核心转储)。使用gdb,回溯如下:

#0  std::pair<double const, cell>::pair<double, A::cell, true> (__p=..., this=<optimized out>) at /usr/include/c++/7/bits/stl_pair.h:362
#1  __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<double const, A::cell> > >::construct<std::pair<double const, A::cell>, std::pair<double, A::cell> > (this=<optimized out>, __p=<optimized out>) at /usr/include/c++/7/ext/new_allocator.h:136
#2  std::allocator_traits<std::allocator<std::_Rb_tree_node<std::pair<double const, A::cell> > > >::construct<std::pair<double const, A::cell>, std::pair<double, A::cell> > (__a=..., __p=<optimized out>) at /usr/include/c++/7/bits/alloc_traits.h:475
#3  std::_Rb_tree<double, std::pair<double const, A::cell>, std::_Select1st<std::pair<double const, A::cell> >, std::less<double>, std::allocator<std::pair<double const, A::cell> > >::_M_construct_node<std::pair<double, A::cell> > (this=0x7fffffffd6d0, __node=0x55555585ed90) at /usr/include/c++/7/bits/stl_tree.h:626
#4  std::_Rb_tree<double, std::pair<double const, A::cell>, std::_Select1st<std::pair<double const, A::cell> >, std::less<double>, std::allocator<std::pair<double const, A::cell> > > >::_M_create_node<std::pair<double, A::cell> > (this=0x7fffffffd6d0) at /usr/include/c++/7/bits/stl_tree.h:643
#5  std::_Rb_tree<double, std::pair<double const, A::cell>, std::_Select1st<std::pair<double const, A::cell> > > std::less<double>, std::allocator<std::pair<double const, A::cell> > >::_M_emplace_unique<std::pair<double, A::cell> > (this=this@entry=0x7fffffffd6d0) at /usr/include/c++/7/bits/stl_tree.h:2351
#6  0x0000555555596ddd in std::map<double, A::cell, std::less<double>, std::allocator<std::pair<double const, A::cell> > >::emplace<std::pair<double, A::cell> > (this=0x7fffffffd6d0) at /usr/include/c++/7/bits/stl_map.h:569
#7  A::doSomething (this=this@entry=0x5555558082d0, points=std::vector with 49 elements = {...}) at ...

回溯并没有使问题变得明显,但进一步的调试表明,从结构中删除均值和协方差允许应用程序运行而不会出错。我可以将它们分成单独的参数,但在我看来这并不是正确的解决方案。也许在制作一对时复制调用会导致问题和本征参数的处理管理不善?任何有助于理解和解决我的问题的帮助将不胜感激。

标签: c++structsegmentation-faultstdmap

解决方案


我认为您必须首先定义该对的类型: std::pair<double,cell> new_pair = makepair(y,cell)然后将其插入到地图中。


推荐阅读