SIGSEGV при использовании pt :: ptree :: value_type для большого числа json матриц - PullRequest
0 голосов
/ 12 февраля 2020

Я пытаюсь проанализировать следующий файл json, который состоит в основном из json матриц из 4 значений. Я использую boost 1.63 на виртуальной машине Ubuntu 16.04.

{ 
   "root":[ 
      { 
         "name":"test1"
      },
      { 
         "name":"test2",
         "value":{ 
            "matrices":[ 
               [ 
                  23.097432,
                  23.702008,
                  27.904633,
                  32.091423
               ],
               [ 
                  67.655115,
                  11.791152,
                  57.539848,
                  52.043283
               ],
               [ 
                  58.767643,
                  71.813496,
                  78.539024,
                  52.252256
               ],
               [ 
                  68.097432,
                  81.702008,
                  97.904633,
                  72.091423
               ]
            ]
         }
      }    
   ]
}

Я использую следующий код:

#include <string>
#include <iostream>
#include <sstream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

using namespace std;
namespace pt = boost::property_tree;

int main()
{
    try
    {
        std::ifstream file("json.txt");
        std::string json_string((std::istreambuf_iterator<char>(file)),

                                 (std::istreambuf_iterator<char>()));

        std::stringstream ss;
        ss << json_string;
        boost::property_tree::ptree pt;
        boost::property_tree::read_json(ss, pt);
        for (auto &e : pt.get_child("root"))
        {
            auto name = e.second.get<std::string>("name");
            if (name == "test2")
            {
                int x = 0;
                for (pt::ptree::value_type &row : e.second.get_child("value.matrices"))
                {
                    for (pt::ptree::value_type &cell : row.second)
                    {
                        double matrix[4];
                        matrix[x] = cell.second.get_value<double>();
                        cout << matrix[x] << endl;
                    }
                    x++;
                }
            }
        }
    }
    catch (const std::exception &exc)
    {
        cout << exc.what() << endl;
    }
    return 0;

}

Когда я запускаю его для 4 матриц, он прекрасно работает.

Однако, когда матрицы равны 100, я получаю следующую ошибку сегментации:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00005566e3c630cc in boost::multi_index::multi_index_container<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, boost::property_tree::basic_ptree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, boost::multi_index::indexed_by<boost::multi_index::sequenced<boost::multi_index::tag<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<boost::property_tree::basic_ptree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::subs::by_name, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::multi_index::member<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, boost::property_tree::basic_ptree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >, std::_---Type <return> to continue, or q <return> to quit---
_cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, &std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, boost::property_tree::basic_ptree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::first>, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, boost::property_tree::basic_ptree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > > >::header (
    this=0x40364093d9663843) at /usr/local/include/boost/multi_index_container.hpp:525
525     return &*bfm_header::member;

Когда я уменьшаю матрицы до 4, все работает нормально.

Поскольку я новичок при использовании Boost Library, что я сделал не так?

Ответы [ 2 ]

2 голосов
/ 12 февраля 2020

Ваша проблема здесь:

 for (pt::ptree::value_type &row : e.second.get_child("value.matrices"))
   {
   for (pt::ptree::value_type &cell : row.second)
   {
    double matrix[4];
    matrix[x] = cell.second.get_value<double>();
    // .....
   }
    x++;
 }   

double matrix[4] всегда содержит 4 элемента (в локальной области ..), и вы увеличиваете x (x ++) из области. Представьте, что for (pt::ptree::value_type &row : e.second.get_child("value.matrices")) делает 10 итераций:
Вы попытаетесь выполнить matrix[9] = cell.second.get_value<double>(); 9> 4 (размер вашего массива), который сгенерирует ошибку сегментации (доступ к массиву вне границ)

1 голос
/ 12 февраля 2020

Ваши матрицы используют пространство в локальном стеке вызовов.

Попробуйте создать для них class, который использует выделенные данные кучи с использованием интеллектуальных указателей и / или некоторого стандарта C ++ контейнер

...