将结构插入地图时出现分段错误

Segmentation fault when inserting struct into a map

正在填充的 mapBase 参数将代表一个坐标系。我使用 std::map 轻松地根据 x 对坐标进行排序,然后与由内部地图排序的 y 坐标配对。内部地图的价值将在以后保存额外的信息。现在它填充了虚拟数据。

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

我尝试添加调试语句,通过使用 std::map::insert 函数的结果并查看结果的第二个字段来告诉我何时成功插入某些内容。这仅在未发生段错误时有用,并且通常总是正确的,因为我在被调用函数的开头清除了 mapBase 。我还尝试使用智能共享指针作为 baseMap 的最终值类型,而不仅仅是结构 object 本身。这并没有改变我的结果。我也尝试分配 *(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;
    }

Header:

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 ...

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

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

你在上面给定的代码片段中有一些错误,我已经删除了。该程序现在可以运行而不会出现分段错误。你可以试试这个并向我确认。

mainneweighen.cpp

#include <vector>
#include <Eigen/Dense>
#include "neweigen.h"
int main(int argc, char **argv)
    {
      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}};
    
    
      std::vector<Eigen::Matrix<double, 2, 1>> points;
      for(const auto& beam : lidarData)
      {
        double x = beam.first * cos(beam.second); // r * cos(theta)
        double y = beam.first * sin(beam.second); // 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;
    }

neweigen.cpp

#include "neweigen.h"

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>());
    }
}

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


neweigen.h

#ifndef FILE_H
#define FILE_H
#include <vector>
#include <Eigen/Dense>
#include <map>
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;
    };


#endif

以上三个文件没有出现任何分段错误。