【问题标题】:Seg fault vector<vector<list<Object*> > > push_backSeg 故障向量<vector<list<Object*> > > push_back
【发布时间】:2010-07-24 17:27:57
【问题描述】:

我有一个像这样定义的 3D 矢量...

std::vector<std::vector<std::list<Object*> > > m_objectTiles;

我有这个代码...

void ObjectManager::AddObject( Object *object ) {
  m_objects.push_back( object );
  m_objectTypes.insert( std::make_pair(
    ObjectAttorney::GetType( object ), object )); 

  int x = ObjectAttorney::GetTileX( object );
  int y = ObjectAttorney::GetTileY( object );
  m_objectTiles[x][y].push_back( object ); // SEG FAULT HERE
}

收到此错误0x0805ccdb in std::vector&lt;std::list&lt;Object*, std::allocator&lt;Object*&gt; &gt;, std::allocator&lt;std::list&lt;Object*, std::allocator&lt;Object*&gt; &gt; &gt; &gt;::operator[] ( this=0x8157758, object=0x8173f30) at /usr/include/c++/4.4/bits/stl_vector.h:611 { return *(this-&gt;_M_impl._M_start + __n); }

我改成这个来测试一下……

void ObjectManager::AddObject( Object *object ) {
  m_objects.push_back( object );
  m_objectTypes.insert( std::make_pair(
    ObjectAttorney::GetType( object ), object )); 

  int x = ObjectAttorney::GetTileX( object );
  int y = ObjectAttorney::GetTileY( object );
  std::list<Object*> *l = &m_objectTiles[x][y];
  if ( l ) { // SEG FAULT HERE
    l->push_back( object );
  } else {
    std::cout << "List null.\n";
  }
}

它只是给出一条错误消息,说明段错误发生的位置ObjectManager::AddObject (this=0x81577a0, object=0x8165760) at ObjectManager.cpp:381 if ( l ) {

为什么在测试空指针时会出现段错误?显然 operator [] 正在返回损坏或无效的内容。不知道这里有什么问题。任何帮助表示赞赏。谢谢。

【问题讨论】:

  • 作为起点,您可以将std::vector&lt;std::vector&lt;std::list&lt;Object*&gt; &gt; &gt; 替换为一些封装类...

标签: c++ list 3d vector segmentation-fault


【解决方案1】:

std::vector[] 出于性能原因不进行范围检查。显然,如果 xy 超出范围,则第二个变体无济于事。

添加这样的检查:

m_objectTiles.size() < x && m_objectTiles[x].size() < y

从引用的代码中很难判断,但可能是您希望 std::vector 自动增长。它不会。为此,您需要类似的东西:

m_objectTiles.resize(x);
m_objectTiles[x].resize(y);

在访问m_objectTiles[x][y]之前。

【讨论】:

  • 这实际上都是在列出的代码之外完成的(向量在构造函数时被调整为特定大小,并且 GetTileX 和 GetTileY 保证返回边界坐标)。
  • 这实际上让我认为调整大小在 ObjectManager 的创建过程中执行得太早了。不会详细介绍,但这导致问题得到解决。谢谢。
【解决方案2】:

您的问题最可能的原因是 ObjectAttorney::GetTileX 和 ObjectAttorney::GetTileY 返回超出范围的值,您检查了吗?

故障转储将if语句指示为崩溃站点的原因可能是旧的调试数据,只需重建您的项目即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多