Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ boost::multi_阵列上的分段错误_C++_Segmentation Fault_Boost Multi Array - Fatal编程技术网

C++ boost::multi_阵列上的分段错误

C++ boost::multi_阵列上的分段错误,c++,segmentation-fault,boost-multi-array,C++,Segmentation Fault,Boost Multi Array,以下代码给出了分段错误: #include <iostream> #include <fstream> #include "binItr.h" #include <boost/multi_array.hpp> using namespace std; int main(){ const char * xifile = "results/feretxiG1155V0P5T231K10.bin"; const uint pSize = 5;

以下代码给出了分段错误:

#include <iostream>
#include <fstream>
#include "binItr.h"
#include <boost/multi_array.hpp>

using namespace std;

int main(){
   const char * xifile = "results/feretxiG1155V0P5T231K10.bin";

   const uint pSize = 5;
   const uint T = 231;

   ifstream xiFileId(xifile, ios::binary);

   typedef boost::multi_array<uint, 2> array_type;
   array_type xi(boost::extents[T][pSize + 1]);

   //the ii_t class in the following line is taken from http://stackoverflow.com/questions/1855704/c-binary-file-i-o-to-from-containers-other-than-char-using-stl-algorithms written by http://stackoverflow.com/users/14065/loki-astari

   ii_t<uint> xi_in(xiFileId);

   copy(xi_in, ii_t<uint>(), xi.data());
   return 0;
}
有什么建议吗?
谢谢。

问题在于,来自的
ii_t
输入迭代器类正在“读取”过多的项,因为包装的
istream
直到迭代器在返回文件中最后一项的迭代器之后取消对该迭代器的引用后才会返回
EOF
。额外返回的数据项正在损坏
multi\u数组
对象中分配的内存块

如果您将
ii_t
类更改为以下内容,您应该获得更好的行为:

template<typename T>
struct ii_t: public iterator<input_iterator_tag, void, void, void, void>
{
  ii_t(std::istream& str)
    :m_str(&str)
  {}
  ii_t()
    :m_str(NULL)
  {}
  ii_t& operator++()   {return *this;}  // increment does nothing.
  ii_t& operator++(int){return *this;}
  T& operator*()
  {
    // On the de-reference we actuall read the data into a local //// static ////
    // Thus we can return a reference
    static T result;
    m_str->read(reinterpret_cast<char*>(&result),sizeof(T));
    return result;
  }
  // If either iterator has a NULL pointer then it is the end() of stream iterator.
  // Input iterators are only equal if they have read past the end of stream.
  bool operator!=(ii_t const& rhs)
  {
      // we need to make sure we're not just about to hit EOF
      // if we already haven't
      if (m_str && m_str->good()) {
        char dummy;
        m_str->read(&dummy,1);
        if (m_str->good()) {
            m_str->putback(dummy);
        }
      }

      if (rhs.m_str && rhs.m_str->good()) {
        char dummy;
        rhs.m_str->read(&dummy,1);
        if (rhs.m_str->good()) {
            rhs.m_str->putback(dummy);
        }
      }

      bool lhsPastEnd  = (m_str == NULL)     || (!m_str->good());
      bool rhsPastEnd  = (rhs.m_str == NULL) || (!rhs.m_str->good());

      return !(lhsPastEnd && rhsPastEnd);
  } 

  private:
    std::istream*   m_str;
};
模板
结构ii_t:公共迭代器
{
ii_t(标准::istream和str)
:m_str(&str)
{}
二()
:m_str(空)
{}
ii_t&operator++(){return*this;}//增量什么也不做。
ii_t&operator++(int){return*this;}
T&运算符*()
{
//在取消引用时,我们实际上将数据读入本地/////静态////
//因此,我们可以返回一个引用
静态T结果;
m_str->read(重新解释强制转换和结果),sizeof(T));
返回结果;
}
//如果任一迭代器具有空指针,则它是流迭代器的end()。
//输入迭代器只有在读取超过流末尾时才相等。
布尔运算符!=(ii_t const&rhs)
{
//我们需要确保我们不仅仅是要达到EOF
//如果我们还没有
如果(m_str&&m_str->good()){
模拟字符;
m_str->read(&dummy,1);
如果(m_str->good()){
m_str->putback(虚拟);
}
}
if(rhs.m_str&&rhs.m_str->good()){
模拟字符;
rhs.m_str->read(&dummy,1);
如果(rhs.m_str->good()){
rhs.m_街->回撤(虚拟);
}
}
bool lhsPastEnd=(m_str==NULL)|(!m_str->good());
bool rhsPastEnd=(rhs.m_str==NULL)| |(!rhs.m_str->good());
返回!(左侧和右侧);
} 
私人:
std::istream*m_街;
};
相关更改在
bool运算符中=(ii_t const&rhs)
功能,如有必要,对包装的
istream执行虚拟读取(然后撤消),以确定istream是否处于EOF


请注意,我并没有声称这是处理
EOF
情况的最佳技术,但它似乎有效。

据我所知,似乎没有什么问题,但你能提供更多关于ii\t的信息吗?还有,你试过通过valgrind运行它吗?我试过valgrind,它没有提到任何内存泄漏。我是从哪里来的。最后,我通过不使用ii_t:)解决了这个问题。如果你注释掉copy()行,它仍然是segfault吗?@fileoffset是的,你是对的。这是抄袭来的,但是因为ii_t类。当我移除它时,seg故障消失了,尽管它花费了我太多的时间:)好的。迈克尔似乎已经解决了这个问题。但是这个ii_t类不是为读取复杂类而设计的,比如
boost::multi_array
。复杂类具有构造函数,此迭代器使用read()对对象进行写操作。这会破坏原始内容。这个类只设计用于POD类型(即没有构造函数的任何类型,如果一个非其成员的结构有构造函数的话)。非常感谢。已验证分段冲突现在不存在。确定。我明白问题所在。std::copy将在++操作后检查流的状态。但因为这没有任何作用,所以它永远是真实的。因此,当您取消引用它(并且它失败)时,它无法知道它出错了,因此使用的对象现在是最后一个对象的副本。在这种情况下,我们现在有两个使用相同内部缓冲区的数组对象。这会导致用户代码出现双重删除和其他与共享缓冲区相关的问题。因此,如上所述,OP问题ii_t的设计不适用于非POD类型。(注意:这并没有改变Michael已经修复了POD类型的代码的事实)。@Loki:我不认为问题是用户错误——这是在从文件中读取最后一项之后,EOF没有被设置,因此迭代器与“空”迭代器不相等。这表明另一个数据引用是正常的-但该数据引用的读取将返回EOF而不是数据(因此
静态T结果保持不变)。我不认为我在
ii_t
中添加的内容是处理此问题的最佳方法,但如果不完全更改
ii_t
,这似乎是最简单的方法@Michael Burr:你是对的。我只是需要一些时间来分析用法(并删除了该评论)。你的方法很好-(
template<typename T>
struct ii_t: public iterator<input_iterator_tag, void, void, void, void>
{
  ii_t(std::istream& str)
    :m_str(&str)
  {}
  ii_t()
    :m_str(NULL)
  {}
  ii_t& operator++()   {return *this;}  // increment does nothing.
  ii_t& operator++(int){return *this;}
  T& operator*()
  {
    // On the de-reference we actuall read the data into a local //// static ////
    // Thus we can return a reference
    static T result;
    m_str->read(reinterpret_cast<char*>(&result),sizeof(T));
    return result;
  }
  // If either iterator has a NULL pointer then it is the end() of stream iterator.
  // Input iterators are only equal if they have read past the end of stream.
  bool operator!=(ii_t const& rhs)
  {
      // we need to make sure we're not just about to hit EOF
      // if we already haven't
      if (m_str && m_str->good()) {
        char dummy;
        m_str->read(&dummy,1);
        if (m_str->good()) {
            m_str->putback(dummy);
        }
      }

      if (rhs.m_str && rhs.m_str->good()) {
        char dummy;
        rhs.m_str->read(&dummy,1);
        if (rhs.m_str->good()) {
            rhs.m_str->putback(dummy);
        }
      }

      bool lhsPastEnd  = (m_str == NULL)     || (!m_str->good());
      bool rhsPastEnd  = (rhs.m_str == NULL) || (!rhs.m_str->good());

      return !(lhsPastEnd && rhsPastEnd);
  } 

  private:
    std::istream*   m_str;
};