Saturday, 20 September 2014

A (bug) blast from the past

Its the beginning of a new school year and the beginning of a whole new set of technical blogs. For this semester's technical course, we have Advanced debugging, with the program's well respected teacher. In this course, we look at ways to solve bugs of any sorts, high and low level, memory leaks, wrong memory allocation and sorts.


To start off this year, I wish to go back and discuss a simple but yet deadly bug which took place during object deletion. This was second year when I was creating my bullet hell game, Bullet Devil, and was creating my own mangers with std::vectors. Theses vectors contained pointers to objects which were being managed, bullets in this case, which could be modified by the manager. The bug occurred when I was deleting bullets with my manager, with the following code.

            if (BulletVector.at(i)->    b_hit==true)//true
            {
                BulletVector.at(i)->~Bullet();// calls the bullet
                BulletVector.erase(i);// erases that object    
           }    



The problem was that the bug would trigger after a random number of bullet destroys, sometimes after 5 bullets, sometimes after 20.  The visual studio disassemble wouldn't help either, directing me to the spot where I knew was the issue.

The solution came when a good programming friend of mine came to help point out what was the issue with this was.The problem was that next iteration of the loop will increase the variable i, but there was also an element removed. This means everything after the deleted element has moved back one step, but the i variable will be 1 element ahead.
To fix this everything in the array after the removed element, we simple decrement the i variable by 1. So if the i variable increases AND things moved backwards, the i variable will not skip any elements. 

The following code fix was:

               BulletVector.at(i)->~Bullet();
               BulletVector.erase(BulletVector.begin()+(i--));// erases that object
               continue;


From this point on, when ever I made a bullet, powerup and enemy manager, for c++, I always included this segment of code.

No comments:

Post a Comment