2013-04-09 3 views
0

У меня есть программа, где у меня есть зЬй :: вектор в качестве члена класса:C++ станд :: вектор :: ясно() аварии

class Blackboard 
{ 
public: 
    inline std::vector<Vector2<int> > GetPath()   
    { return m_path; } 

    inline void SetPath(std::vector<Vector2<int> > path) 
    { m_path = path; } 

    inline void ClearPath()           
    { if(m_path.size() > 0) m_path.clear(); } 

private: 
    std::vector<Vector2<int>> m_path; 
}; 

Если класс Vector2 определяется как:

template <class T> 
class Vector2 
{ 
private: 
    T m_x; 
    T m_y; 

public: 
    Vector2(void) 
    { m_x = 0; m_y = 0;} 

    Vector2(T x, T y)           
    { m_x = x; m_y = y;} 

    ~Vector2(void)          
    { } 

    inline T x() const         
    { return m_x; } 

    inline T y() const         
    { return m_y; } 

    // ... 
}; 

И в какой-то момент я называю:

m_blackboard.ClearPath(); 

Это прекрасно работает в отладке, но сбои в версии с «Microsoft Visual Studio C Runtime библиотеки имеет д etected фатальная ошибка в Test2.exe. " сообщение.

Стек вызовов, в последний момент, когда я все еще могу видеть, показывает, что:

Test2.exe!std::vector<RBT::Vector2<int>, 
std::allocator<RBT::Vector2<int> > >::erase 
(std::_Vector_const_iterator<RBT::Vector2<int>, 
std::allocator<RBT::Vector2<int> > > 
_First_arg={m_x=15 m_y=7 }, 
std::_Vector_const_iterator<RBT::Vector2<int>, 
std::allocator<RBT::Vector2<int> > > 
_Last_arg={m_x=15 m_y=8 }) Line 1037 + 0xe bytes C++ 

EDIT: Вот где я звоню код, который заканчивает сбоями:

BTNode::Status GoToDestBehavior::Update() 
{ 
    BTEntityData::Node* node = m_dataRef->m_bTree.GetNode(m_index); 
    if(node->m_state == BTNode::STATE_READY) 
    { 
     BehaviorTree::RequestDeferredAction(Batch::PATHFIND, m_dataRef->m_entityID); 
     return BTNode::STATE_RUNNING; 
    } 
    else if(node->m_state == BTNode::STATE_RUNNING) 
    { 
     std::vector<Vector2<int>> path = m_dataRef->m_blackboard.GetPath(); 

     EntitySystem::Entity* entity = EntitySystem::GetEntity(m_dataRef->m_entityID); 
     Assert(entity != NULL, "Invalid entity\n"); 

     Assert(entity->HasComponent(Component::PHYSICS_COMP), "Associated entity must have physics component to move\n"); 
     int phyIndex = entity->GetComponentIndex(Component::PHYSICS_COMP); 

     PhysicsSystem::PhysicsData * physicsData = PhysicsSystem::GetComponent(phyIndex); 
     Assert(physicsData != NULL, "Invalid physics data\n"); 

     // Path is empty, so finish 
     if(path.size() == 0) 
     { 
      physicsData->m_dir = Direction::NONE;  // Stop because we are here 
      return BTNode::STATE_SUCCESS; 
     } 

     // Remove last element if we are at it 
     //LogFmt("Size of vector %d\n", path.size()); 
     Vector2<int> last = path.back(); 
     if(last.x() == physicsData->m_posX && last.y() == physicsData->m_posY) 
     { 
      path.pop_back(); 
     } 

     // Last node of the path has been transversed 
     if(path.size() == 0) 
     { 
      physicsData->m_dir = Direction::NONE;  // Stop because we are here 
      m_dataRef->m_blackboard.ClearPath(); 
      return BTNode::STATE_SUCCESS; 
     } 

     Vector2<int> step = path.back();     

     physicsData->m_dir = Direction::VectorToDirection(physicsData->m_posX, physicsData->m_posY, step.x(), step.y()); 
     if(physicsData->m_dir == Direction::NONE) 
     { 
      m_dataRef->m_blackboard.SetPath(path); 
      return BTNode::STATE_FAIL; 
     } 
     m_dataRef->m_blackboard.SetPath(path); 
     return BTNode::STATE_RUNNING; 
    } 

    return BTNode::STATE_ERROR; 
} 

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

Другая вещь, о которой я могу думать, это мой класс Vector2, требующий какого-то конструктора копирования или что-то еще, когда я добавляю элементы в вектор, но в итоге это всего лишь 2 ints, поэтому я не знаю, почему это может потерпеть неудачу.

Я слишком много над этим кодом и, возможно, пропустил что-то очевидное. Вся помощь будет принята с благодарностью.

Спасибо заранее, Jaime

+7

Совершенно нормально называть 'clear()' на пустом векторе, проблема в другом месте, то есть, скорее всего, ваша программа имеет неопределенное поведение до того, как этот код даже выполнен. –

ответ

2

Это прекрасно, чтобы позвонить clear на пустой контейнер любого рода.

Используя мои умственные навыки отладки, я определил, что в коде вы не показываете нам, что получаете доступ к элементам vector, которые на самом деле не существуют (возможно, до того, как вы их вставили, и, вероятно, с operator[]). Обычно создание элемента осуществляется через resize, push_back, или insert.

Другая возможность заключается в том, что у вас есть другое повреждение памяти где-то в вашей программе.

+0

Отредактировано, чтобы показать полный вызов, когда он аварии, пожалуйста, смотрите. – JaimeBarrachina

+2

@JaimeBarrachina Вам нужно уйти от идеи, что место, где происходит сбой кода, каким-то образом связано с местом, где есть ошибка. Это может быть, но только возможно. Для меня ваша ошибка звучит как куча коррупции, которая могла произойти в любой части вашей программы. Я бы посмотрел на части вашей программы, которые выделяют память новыми и/или манипулируют указателями. – john

0

Я обнаружил, что проблема была связана с изменением формата данных. Список std :: list, который я использовал, был изменен из указателя на список, чтобы непосредственно перечислить список. Это вызвало всевозможные ошибки, которые проверяли размер списка, и не вызвали вызов ZeroMemory()/memset(), который уничтожил все данные отслеживания списка, поскольку теперь он был частью вместо указателя на список.

Если у вас есть пустой список и вызывается .clear() на нем сбой, возможно, вы перепутали внутреннюю память слежения, как упоминал Марк в его ответе. Ищите место, где вы делаете очистку памяти на содержащих классы и тому подобное, как наиболее вероятные преступники.

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