2016-10-05 3 views
2

i'm написать код, для которого я использую трехмерный boost multiarray для сохранения координат. Но в какой-то момент я всегда получаю ошибку сегрегации. Как ограничить размеры multiarray и как я могу обойти эти ограничения?boost multiarray segementation fault

Вот упрощенный тестовый код, который воспроизводит проблему:

#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; 
} 

Пожалуйста, не прокомментировать включает. Я просто копирую и вставляю код. Большинство из них, вероятно, здесь не нужны. Размеры взяты из реального примера, поэтому мне действительно нужны такие размеры (и, вероятно, больше).

Большое спасибо ....

+0

'lgr.grid [j] [k] [l] = & (vertexDB.back());' - Не рекомендуется хранить указатели на элементы в векторе. Если вектор становится измененным, то итераторы и указатели на предметы становятся недействительными. – PaulMcKenzie

ответ

2

Следующая определенная проблема, которая приводит к неопределенному поведению, и не имеет ничего общего с boost::multiarray.

Эти строки:

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

изменяет размер vertexDB вектор, а затем хранит указатель на последний элемент в векторе на lgr.grid[j][k][l]. Проблема в том, что указатели и итераторы для элементов в векторе могут стать недействительными из-за того, что вектор должен перераспределять память при изменении размера вектора.

Это проявляется позже здесь, в следующем цикле:

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

Там нет никакой гарантии, что адрес, который вы назначены ранее является действительным.

Быстрое исправление для этого состоит в использовании std::list<Vertex>, так как добавление элементов в std::list не делает недействительными итераторы/указатели.

+0

ОК, теперь я чувствую себя глупо. После того, как вы объяснили это, это очевидная проблема. И использование List отлично работает для тестового кода (к сожалению, я не могу проверить реальный код, потому что каким-то образом класс, который мне нужен, полностью уничтожен, и теперь мне нужно его воссоздать .....). Хорошо, что угодно, это работает. Спасибо, PaulMcKenzie ... – Myrkjartan

Смежные вопросы