简体   繁体   中英

boost multiarray segmentation fault

I`m writing a code for which I'm using a 3 dimensional boost multiarray to save coordinates. But I always get a segmentation fault at some point. How are boost multiarray sizes limited and how can I get around those limits?

Here is a simplified test code that reproduces the problem:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <string>
#include <algorithm>
#include <map>

#include <boost/multi_array.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include "Line.h"

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>

typedef struct {
    Eigen::Vector3d coords;
    int gpHostZone;
    int gpHostFace;
    int calculated;
} Vertex;


class LGR {
public:
    LGR (int i, int j, int k) :
        grid(boost::extents[i][j][k])
    {
    };

    std::string name;
    std::vector<int> hostZones;
    std::vector<int> refine;
    boost::multi_array<Vertex*, 3> grid;
    std::vector<double> data;
 };

 int main(void){
   LGR lgr(11,11,21);
   std::cout << lgr.grid.size();
   std::vector<LGR> v;
   std::vector<Vertex> vertexDB;
   for(int i = 0; i < 1; i++ ){

     for(int j = 0; j < lgr.grid.size(); j++ ){
       for(int k = 0; k < lgr.grid[0].size(); k++ ){
         for(int l = 0; l < lgr.grid[0][0].size(); l++ ){
           Vertex coord;
           coord.coords << i,j,k;
           coord.gpHostZone = 0;
           coord.gpHostFace = 0;
           coord.calculated = 0;
           vertexDB.push_back(coord);
           lgr.grid[j][k][l] = &(vertexDB.back());
         }
       }
     }

     for(int j = 0; j < lgr.grid.size(); j++ ){
       for(int k = 0; k < lgr.grid[0].size(); k++ ){
         for(int l = 0; l < lgr.grid[0][0].size(); l++ ){
           std::cout << "At ("<< i << ","<< j << ","<< k << "," << l << ")\n";
           std::cout << lgr.grid[j][k][l]->coords<<"\n\n";
         }
       }
     }
   }
   return 1;
 }

Please do not comment on the includes. I just copy and pasted from the actual code. Most of the are probably not needed here. The dimensions are from a real example, so I actually need those kind of dimensions (and probably more).

The following is a definite issue that leads to undefined behavior, and doesn't have anything to do with boost::multiarray .

These lines:

std::vector<Vertex> vertexDB;
//...
vertexDB.push_back(coord);
lgr.grid[j][k][l] = &(vertexDB.back());

resizes the vertexDB vector and then stores a pointer to the last item in the vector to lgr.grid[j][k][l] . The problem with this is that pointers and iterators to items in a vector may become invalidated due to the vector having to reallocate memory when resizing the vector.

This manifests itself later here, in the subsequent loop:

std::cout << lgr.grid[j][k][l]->coords<<"\n\n";

There is no guarantee that the address you assigned previously is valid.

A quick fix for this is to use a std::list<Vertex> , since adding items to a std::list does not invalidate iterators / pointers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM