Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (494)
Games in Android Showcase (114)
games submitted by our members
Games in WIP (563)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Array out of bounds error  (Read 2537 times)
0 Members and 1 Guest are viewing this topic.
Offline PRW56

Senior Newbie





« Posted 2012-06-27 00:41:50 »

ok In the game thingy I made, its spawning new dudes every 5 seconds. It adds them to the array list of the corresponding team. I figured that, since it takes up a bit of processing power to constantly resize an arraylist, I should give them all a boolean value (dead), that the redering method checks for before painting them. However the new problem is that if the game goes on, said arrays will become filled with dead, and therefore useless, players. So every 30 seconds I made it so that it goes throught the array, and deletes the dead players. Now here is my problem, at seemeingly random checks, like it will successfully delete the dead once or maby ten times or maby more, it throws an arrray out of bounds error that refuses to be caught. I have no idea why it is doing this, because I ensure the capacity to like 50 for both arraylists too. Any one have an idea of what could cause this? The entire code is really long, but here is what causes the problem (bluep and redp are the arraylists, i.e. teams):

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
if((cc+600)%600==0)
        {
            System.out.println("Deleting the dead");
            //System.out.println(bluep.size()+"  "+redp.size());
           try
            {
                int x,y;
                for(x=0;x<bluep.size();++x)
                {
                    BlueStick subb = (BlueStick)bluep.get(x);
                    if(subb.isDead()==true)
                    {
                        bluep.remove(x);
                    }
                }
                for(y=0;y<redp.size();++y)
                {
                    RedStick subr = (RedStick)redp.get(y);
                    if(subr.isDead()==true)
                    {
                        redp.remove(y);
                    }
                }
            }
            catch(IndexOutOfBoundsException e)
            {
                //System.out.println("x: "+x+" y: "+y);
               System.out.println(bluep.size()+"  "+redp.size());
            }
        }
Offline philfrei
« Reply #1 - Posted 2012-06-27 00:47:57 »

You might have better luck with a for-each loop when iterating through an ArrayList.

When you make your index, in the existing code, it uses the size of ArrayList at that time as the upper bounds. After a single delete, the true upper bounds will be lower than the bounds of your for loop, hence the exception.

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Offline PRW56

Senior Newbie





« Reply #2 - Posted 2012-06-27 01:09:54 »

ah that makes perfect sense (never heard of a for each loop though...), ty so much for the help! However two things still bug me, one why would it work at all (because somethimes it wouldnt throw an exception), because there were dead plenty of times it checked that should have been deleted. Second why would the exception not be caught by the try catch loop? because I watched the terminal, and it didn't print redp.size().
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline CyanPrime
« Reply #3 - Posted 2012-06-27 02:03:34 »

I say just use a Vector.
Offline theagentd
« Reply #4 - Posted 2012-06-27 04:30:15 »

ok In the game thingy I made, its spawning new dudes every 5 seconds. It adds them to the array list of the corresponding team. I figured that, since it takes up a bit of processing power to constantly resize an arraylist, I should give them all a boolean value (dead), that the redering method checks for before painting them. However the new problem is that if the game goes on, said arrays will become filled with dead, and therefore useless, players. So every 30 seconds I made it so that it goes throught the array, and deletes the dead players. Now here is my problem, at seemeingly random checks, like it will successfully delete the dead once or maby ten times or maby more, it throws an arrray out of bounds error that refuses to be caught. I have no idea why it is doing this, because I ensure the capacity to like 50 for both arraylists too. Any one have an idea of what could cause this? The entire code is really long, but here is what causes the problem (bluep and redp are the arraylists, i.e. teams):

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
if((cc+600)%600==0)
        {
            System.out.println("Deleting the dead");
            //System.out.println(bluep.size()+"  "+redp.size());
           try
            {
                int x,y;
                for(x=0;x<bluep.size();++x)
                {
                    BlueStick subb = (BlueStick)bluep.get(x);
                    if(subb.isDead()==true)
                    {
                        bluep.remove(x);
                    }
                }
                for(y=0;y<redp.size();++y)
                {
                    RedStick subr = (RedStick)redp.get(y);
                    if(subr.isDead()==true)
                    {
                        redp.remove(y);
                    }
                }
            }
            catch(IndexOutOfBoundsException e)
            {
                //System.out.println("x: "+x+" y: "+y);
               System.out.println(bluep.size()+"  "+redp.size());
            }
        }

When you remove something from an ArrayList it shifts all following elements to fill the gap. When you then increase the index again you miss the object that was shifted into the gap, and it will not be removedis b if it's dead. You can fix this by simply doing x--; when calling remove(). That could simply be it.

I say just use a Vector.
Because synchronization solves logic problems?  Tongue

Myomyomyo.
Offline Danny02
« Reply #5 - Posted 2012-06-27 06:35:32 »

seriously, do NOT put so much thought in premature optimization.

Just take any Collection and add and remove Items. If it plays out that this single collection does in any way affect your overall performance in a bad way. You can still think about using some better type of collection.
Offline philfrei
« Reply #6 - Posted 2012-06-28 06:52:26 »

Quote
ah that makes perfect sense (never heard of a for each loop though...), ty so much for the help! However two things still bug me, one why would it work at all (because somethimes it wouldnt throw an exception), because there were dead plenty of times it checked that should have been deleted. Second why would the exception not be caught by the try catch loop? because I watched the terminal, and it didn't print redp.size().

I honestly don't know why your try/catch block did not catch the IndexOutOfBoundsException. Seems like it should have. On what line of code does the error occur? What is an example of an error message? It should state the line, the array and the offending value.

Following is a plausible for:each loop using your variable names --
1  
2  
3  
4  
5  
6  
7  
    for (Bluestick subb : bluep)
    {
        if( subb.isDead() )
        {
            bluep.remove(subb);
        }
    }

The nice thing with the above is that you are dealing directly with the object itself, not an integer index.

Funny things can happen when iterating through an array while deleting its elements. I can't recall if you are allowed to do it in an ArrayList or not.

The Javadoc for ArrayList says: "The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. "

So maybe it will work? (You aren't accessing these arrays from another code location at the same time, are you?)

But it might be better to try and design something where the issue is doesn't even come up, like maybe first copying the array into a new array, then emptying the original array and copying only the live ones back in. There are some nice methods available for array copying.

Then again, as another poster says, keep it simple and don't worry too much about optimizing until you have proof of a need for it.

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Offline ra4king

JGO Kernel


Medals: 345
Projects: 3
Exp: 5 years


I'm the King!


« Reply #7 - Posted 2012-06-28 07:03:18 »

1  
2  
3  
4  
5  
6  
7  
    for (Bluestick subb : bluep)
    {
        if( subb.isDead() )
        {
            bluep.remove(subb);
        }
    }

Yup that does throw a ConcurrentModificationException Wink

One where it doesn't:
1  
2  
3  
4  
5  
6  
7  
Iterator<Bluestick> iter = bluep.iterator();
while(iter.hasNext()) {
    Bluestick subb = iter.next();
   
    if(subb.isDead())
        iter.remove();
}

Offline philfrei
« Reply #8 - Posted 2012-06-28 07:20:15 »

Thanks for the correction ra4king!

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Offline PRW56

Senior Newbie





« Reply #9 - Posted 2012-07-11 10:33:09 »

For some odd reason it is still throwing an exception.

i had to change the code slightly:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
Iterator<BlueStick> iterb = bluep.iterator();
                while(iterb.hasNext())
                {    
                    BlueStick subb = iterb.next();        
                    if(subb.isDead())
                    {
                        iterb.remove();
                    }
                }
                Iterator<RedStick> iterr = redp.iterator();
                while(iterr.hasNext())
                {    
                    RedStick subr = iterr.next();        
                    if(subr.isDead())
                    {
                        iterr.remove();
                    }
                }


I have no idea why its still doing that, I'm also curious why this code also throws the exception:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
for(int x=0;x<bluep.size();++x)
                {
                    //System.out.println("x: "+x);
                   //System.out.println("blue size: "+bluep.size());
                   
                    if(x==(bluep.size()-1))
                        break;
                    BlueStick subb = (BlueStick)bluep.get(x);
                    if(subb.isDead()==true)
                    {
                        bluep.remove(x);
                    }
                }


if it allways breaks out of the for loop on the very last object in the arraylist (before it has a chance to delete it), how is it still accessing past the bounds of the arraylist???

also here is the error code when I tested the iterator (just in case it matters):
Exception in thread "Thread-4" java.lang.IndexOutOfBoundsException: Index: 4, Size: 4
   at java.util.ArrayList.rangeCheck(ArrayList.java:604)
   at java.util.ArrayList.get(ArrayList.java:382)
   at GamePanel.updateGame(GamePanel.java:425)
   at GamePanel.gameLoop(GamePanel.java:145)
   at GameFrame$1.run(GameFrame.java:127)
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 796
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #10 - Posted 2012-07-11 12:17:35 »

If isDead() returns true, this is effectively what happens:

1  
2  
3  
BlueStick subb = (BlueStick)bluep.get(x);
subb.isDead();
bluep.remove(x);

there is no way this can cause an IndexOutOfBoundsException, unless:
  • when isDead() is called, it also changes 'bluep'
  • you have multiple threads running concurrently, which are all modifying 'bluep'

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline PRW56

Senior Newbie





« Reply #11 - Posted 2012-07-11 12:25:13 »

I only have 1 thread, and the method isDead() is:
1  
2  
3  
4  
public boolean isDead()
    {
        return dead;
    }


I don't have the foggiest idea of why it isn't working. I commented out the code and the error stopped, so I know it is coming from there.
Offline philfrei
« Reply #12 - Posted 2012-07-12 04:24:31 »

I'm not sure I understand your post (Reply #9). Are you saying the rewrite, using Iterator, is throwing an Exception? What is the exception, and on what line?

For the second code excerpt, there is an obvious way to throw an out of bounds exception:
- delete of the second to last element.

Let's say your array starts with 10 elements.
On iteration 8, you delete an element.
Next for loop, x == 9, but bluep.size() also equals 9, and bluep.size() - 1 equals 8. So you blow right past your break command.

Do you have a step debugger?

Putting in <= instead of = would perhaps make your code work better, but it would still be less than crystal clear coding.

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Offline Ultroman

JGO Knight


Medals: 25
Projects: 1


Snappin' at snizzes since '83


« Reply #13 - Posted 2012-07-12 04:47:37 »

I'm also curious why this code also throws the exception:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
for(int x=0;x<bluep.size();++x)
                {
                    //System.out.println("x: "+x);
                   //System.out.println("blue size: "+bluep.size());
                   
                    if(x==(bluep.size()-1))
                        break;
                    BlueStick subb = (BlueStick)bluep.get(x);
                    if(subb.isDead()==true)
                    {
                        bluep.remove(x);
                    }
}


if it always breaks out of the for loop on the very last object in the arraylist (before it has a chance to delete it), how is it still accessing past the bounds of the arraylist???

I would think you'd want to remove ALL the dead ones, and not leave 1 left, so why not do this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
for(int x=0; x < bluep.size(); x++)
{
   BlueStick subb = (BlueStick)bluep.get(x);
   if(subb.isDead())
   {
      bluep.remove(x);
      x--;
   }
}

I use that method whenever I need to remove things from ArrayLists and Vectors, while iterating through them. Works fine for me. As far as I can see, you can easily use this same method to fix your other problems.

I know this isn't the most optimal way, and ra4king will probably roll over laughing, but it'll work ;P

- Jonas
Offline sproingie

JGO Kernel


Medals: 202



« Reply #14 - Posted 2012-07-12 05:05:58 »

If you go backward through the list instead of forward, you don't need to readjust x every time you delete.

Those casts also look dubious, but last time I suggested using generics properly, I got no end of grief from it.  Roll Eyes
Offline Ultroman

JGO Knight


Medals: 25
Projects: 1


Snappin' at snizzes since '83


« Reply #15 - Posted 2012-07-12 06:04:01 »

Those casts also look dubious, but last time I suggested using generics properly, I got no end of grief from it.  Roll Eyes
Yeah. I'd do some inheritance here. Make a Stick-class, which holds all the fields and methods that are the same for BlueStick and RedStick, and add an int type to distinguish between the two. Then he would only have lists of the Stick-class, and there'd be no need to cast anything.

- Jonas
Offline PRW56

Senior Newbie





« Reply #16 - Posted 2012-07-12 18:41:11 »

ok ultroman, I tried something almost exactly like the code in post 14, it still threw the exception... but it may have been the way I did it, I was on stupid pills that day. Also, those casts are very... unnecessary, but the whole code was just so I could learn active rendering, and see how well i could do with AI. I learned enough to improve it quite a bit (I hope), I really missused inheritance when I made the Blue/RedStick classes. Ty all for the help!!
Offline Ultroman

JGO Knight


Medals: 25
Projects: 1


Snappin' at snizzes since '83


« Reply #17 - Posted 2012-07-13 02:01:24 »

Well, I hope you figure it out. If you want, I could check your implementation. That method really shouldn't EVER go out of bounds.

- Jonas
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Dwinin (23 views)
2014-09-12 09:08:26

Norakomi (56 views)
2014-09-10 13:57:51

TehJavaDev (69 views)
2014-09-10 06:39:09

Tekkerue (34 views)
2014-09-09 02:24:56

mitcheeb (56 views)
2014-09-08 06:06:29

BurntPizza (40 views)
2014-09-07 01:13:42

Longarmx (25 views)
2014-09-07 01:12:14

Longarmx (31 views)
2014-09-07 01:11:22

Longarmx (31 views)
2014-09-07 01:10:19

mitcheeb (38 views)
2014-09-04 23:08:59
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!