views:

142

answers:

2

I have a 3D vector defined like this...

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

I have this code...

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
}

that receives this error 0x0805ccdb in std::vector<std::list<Object*, std::allocator<Object*> >, std::allocator<std::list<Object*, std::allocator<Object*> > > >::operator[] ( this=0x8157758, object=0x8173f30) at /usr/include/c++/4.4/bits/stl_vector.h:611 { return *(this->_M_impl._M_start + __n); }

I changed it to this to test it...

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

which just gives an error message saying where the seg fault occured ObjectManager::AddObject (this=0x81577a0, object=0x8165760) at ObjectManager.cpp:381 if ( l ) {

Why would a seg fault occur when testing for a null pointer? Obviously operator [] is returning something corrupted or invalid. Not sure what the problem is here. Any help is appreciated. Thanks.

+1  A: 

The most probable cause for your problem is that ObjectAttorney::GetTileX and ObjectAttorney::GetTileY are returning out-of-range values, have you checked them?

The reason for the crash dump to indicate the if statement as the crash site is probably old debugging data, just rebuild your project.

Ramon Zarazua
+2  A: 

std::vector's [] for performance reasons doesn't do range checks. Obviously that second variant doesn't help if x or y are out of range.

Add a check like that:

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

It is hard to judge from the quoted code, but it might be that you want std::vector to grow automatically. It will not. For that you would need something like that:

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

before accessing the m_objectTiles[x][y].

Dummy00001
This is actually all done outside of the code listed (vector is sized to specific size upon constructorion, and GetTileX and GetTileY are guaranteed to return coordinates in bounds).
random
This actually got me thinking that resize was performed too early in ObjectManager's creation. Won't go into the details, but this led to the problem being solved. Thanks.
random