Down the (memory) rabbit hole

I’ve been transitioning the program to fullscreen, from a fixed 800×800 windowed resolution. There are many things involved in doing this, and I actually spent over 10 hours yesterday working on this.* I started working at before 9:00, went to the gym for a workout, and finished working at 9:00 that night. I can only say that the first 8 hours were actually productive, since more than that and I turn into a zombie, only capable of doing grunt work that requires little thought. It was very unfortunate then, that I got a weird bug right then. The damage:

BTW, as always I strongly recommend making the videos fullscreen and 720p.

For reference, this is what the same code looks like fixed:

Let’s say that we need to store a number. We would use an integer. An integer would be, as specified by the programming language c++, 4 bytes of data, or 32bits. That means that when I write something to the effect of int* pNum = new int(); the computer reserves 4 bytes of memory for me that I can use to store an integer. c++ also has something called arrays. These arrays must be of a specified length. Arrays must also be of a specified data type. So if I want to have a series of integers I would write something like this: int nums[16]; which allocates 16*4, or 64bytes of space for me sequentially, which I can use to store my integers.

To access any given element in an array we use the index. So to get the fourth element, I use nums[3], since the first element is nums[0]. The number inside the [ ] is called the offset. The way this works is the computer returns the value inside the memory location that is the product of the offset, and the size of the data. So nums[3] starts at the start of nums, and then goes 4*3 bytes later, or 12 bytes later, and reads in the integer stored there.

What’s important about this, is that I can easily write nums[88], which isn’t a valid index, and is trying to access a memory location that I haven’t set. This is quite dangerous when reading in data, but is hugely dangerous when writing data. Some programming languages, such as Java, will give “array out of bounds” error messages and crash when the program attempts to access a location that is outside the array. This is a bit slower though, and c++ does not do this. What that means, is that you can read from an invalid location, and, more dangerously, write to an invalid location, and the program will continue along as if nothing has happened.

The bug, like about half of my bugs, was a copy and paste error. I had one large class that controlled all the sprinkler projectiles in the game, called sprinklerbolts. It has a bunch of arrays that were all supposed to be of size 128, such as xPos[128], or isAlive[128]. Unfortunately, I copied and pasted some code that was only of array size 16. This meant that the program wrote to, for each array that was done this way, 104 invalid locations after it, when the object was being created. Additionally, I would get errors when I tried to move the bolts, create a new one, and basically do anything with them logic wise.

Interestingly, all the characters in the game, the NPC’s and the PC, are all allocated on the stack. The stack is a small, by modern standards, amount of memory allocated to each program at startup. This is in contrast to the free store, or heap, which is the memory of the computer that is not in use, and can be allocated and deallocated manually. As of right now, only the graphics and sound data uses the heap, everything else is created on the stack. Because of this, the problem was perfectly repeatable. The exact same memory locations were overwritten the exact same way at the exact same times from one run to the next. Had I allocated the bolts on the heap, they would have had a random location in memory, and the problem would not have been reproducible exactly.

When I found the location of the bug absolutely everything got fixed immediately. It was almost surreal. A few correct number changes and the program worked beautifully again. In one sense though, when you’re overwriting the memory of random things in the program with semi-random values, you’re bound to have lots of weird errors.

There were some slight changes I made. The black bars are now rendered, and I fixed the health bar, which wasn’t rendering properly. Aside from that, there are no differences. I love how the base, the grey area, has its left half sliding around at timed intervals. It’s just so interesting watching how some things went all to hell, and some things were totally unchanged.

*Mostly this was because I needed to convert the game logic to units, instead of pixels, and then manually do conversions later. I’ll make an actual post about this later.

This entry was posted in Monochrome, Programming. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s