[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[pygame] Subtle Memory Bug



I've just solved a tricky bug (I think) whose solution might help others
who encounter a similar problem.

I was playing with cellular automata, a bunch of "tribes" that move and
grow as squares on a grid. Each tribe was stored in a game object, in a
dictionary, by an ID number. I had a loop that made each tribe take an
action, like so:

for tribe in self.alltribes.values(): ## Line 1
    ## Make sure tribe is still in play before activating.
    if tribe.ID in self.alltribes.keys(): ## Line 2
        tribe.Go()
self.age += 1

Some events would cause a tribe to merge with another, deleting both and
creating a new tribe with a new ID value. Other events would create a
new tribe. I was getting a strange error in which a tribe would try to
move from coordinates that it wasn't actually at, crashing the program.
I narrowed down that this only happened when a tribe was deleted, and
then another tribe was randomly created with the same ID in the same turn.

The reason seems to be this. Line 1 creates a list of tribes when the
loop begins, _containing the tribe objects themselves_. When a game
event deletes a tribe, it's still present in memory until the end of the
loop... so the loop checks the deleted tribe's ID, sees that there's
still a tribe with that ID (the newly created one), and runs _the
deleted tribe_, which shouldn't happen. So I changed line 2 to:

if tribe in self.alltribes.values(): ## Line 2b

This way, the tribe is checked not as an ID#, but as a Python object,
against the list of objects in self.alltribes.values. If the tribe is
deleted, it won't show up in the list when it's checked, so the test
will fail as it should.

Anyway, I learned something from this problem about the persistence of
objects in memory. Perhaps this will help someone else.

Kris
...Defeated the Bug and got 1 experience points!