프로그래밍/C,C++

Debug Assertion Failed! vector subscript out of range Line: 932

채윤아빠 2014. 1. 13. 01:31
728x90
반응형

증상 및 문제점

  • STL의 vector를 사용하던 중에 다음과 같은 오류가 발생하며 프로그램이 중단된다.


원인

  • 한줄 한줄 vector를 사용하는 부분을 디버깅하여 본 결과, vector를 참조하는 색인 값을 vector의 실제 크기보다 큰 값을 잘못 입력하여 발생하는 문제입니다.
  • 유사한 오류 발생 예제
    #include <SFML/Graphics.hpp>
    #include "player.h" 
    #include "enemy.h" 
    #include <vector>
    #include <iostream>
    using namespace sf;
    
    int main()
    {
        RenderWindow window(VideoMode(800,600), "Deine mudda");
    
        Clock clock;
        int timecount = 0;
        std::vector<Enemy> enemyv;
        Player player1("player.png");
        while (window.isOpen())
        {
            Event event;
    
            float timepassed = clock.restart().asMilliseconds();
            timecount += timepassed;
    
            while(window.pollEvent(event))
            {
                if (event.type == Event::Closed)
                    window.close();
            }
    
            if (timecount >= 500)
            {
                Enemy enemyx = Enemy("enemy.png");
                enemyv.push_back(enemyx);
                timecount = 0;
            }
    
            window.clear(Color(0,100,200));
            size_t nSize = enemyv.size()
            for (int i = 0; i < nSize; i++)
            {   
                if (!enemyv[i].Active)
                {
                    enemyv.erase(enemyv.begin() + i);
                }
    
                enemyv[i].Update(window);
                enemyv[i].Render(window);
            }
    
            player1.Update(window);
            player1.Render(window);
    
            window.display();
        }
    }
    

해결책

  • "Expression: vector subscript out of range" 오류는 vector의 크기를 벗어하는 데이터 항목을 참조하려고 할 때 발생하는 문제임을 명심하고,
  • vector 내의 데이터 항목을 잘못 참조하지 않도록 색인 값을 잘 관리해야 합니다.
  • 위 예제의 경우, vector의 항목들을 검사하여 특정 조건을 만족하면 중간에 vector의 항목을 삭제하도록 되어 있습니다.
  • 그래서 하나라도 조건에 만족하여 해당 항목이 삭제되면, 마지막 부분에 가서 이미 삭제된 항목으로 인하여 범위를 벗어하는 데이터 항목을 참조하게되어 위와 같은 오류가 발생합니다.
  • 가장 손쉬운 방법은 순서가 중요하지 않다면 for문의 index를 감소하는 식으로 거꾸로 vector를 순환하며 처리하면 됩니다.
            for (int i = enemyv.size() - 1 ; i >= 0 ; i--)
            {   
                if (!enemyv[i].Active)
                {
                    enemyv.erase(enemyv.begin() + i);
                }
    
                enemyv[i].Update(window);
                enemyv[i].Render(window);
            }