Monochrome Programming: Bugs

PROGRAMMING PART 4 – Bugs, Miscellaneous

Not everything that compiles actually works, and I got my share of bugs, from serious and irritating, to completely trivial. There are categories of bugs that I got that are not listed here, but these are the most common.

ONE DEEP POINTERS vs TWO DEEP POINTERS

A pointer is just a variable that stores the address of another variable. This is useful for a variety of different reasons, some for performance, some for functionality. Imagine that we had a massive struct that was 1MB in size (okay not massive compared to what it could be but still). If we have to pass that struct into a function, then C and C++ make copies of that struct. This means that we are utilizing an extra 1MB of memory, and using the CPU cycles to copy 1MB of memory to another 1MB of memory. This is wasteful. We might instead want to create a very small variable that points to where the struct resides in memory. Then we simply pass this tiny variable to the function, make a tiny copy of the variable, and we’re happy. Considering the way that CPU caches miss, I’ve been informed that this might actually not be a performance benefit if a lot of data is being read from the struct, however, there is another benefit.

It’s possible that we want to change some or all of the values in the structure. If we pass in the naked structure, then, since C makes a copy of the structure, we simply change the values in the copy, instead of the values in the actual struct. As a code example:

void MakeXEqual4(fakeStructType someStruct){
someStruct.x=4;
}

fakeStructType fakeStruct;
fakeStruct.x=3;
MakeXEqual4(fakeStruct); //only changes the copy.
std::cout << fakeStruct.x << ‘\n’;
//we will see that the x value is still 3.

This is true of all variables, not just structs, and can be solved in one very easy way, by using pointers. Since pointers store the memory address of a variable, it doesn’t matter if they get copied, since the memory address will still point to the same variable. As an example:

void MakeEqualToFour(int* pInt){
*pInt=4;
}

int someInt=3;
int* pSomeInt=&someInt;
MakeEqualToFour(pSomeInt);
std::cout << someInt << ‘\n’;
//someInt will equal 4.

In real life, I would just pass in the address of someInt to the function, and not have to waste a line creating a pointer, but the point remains. Also, we could go the functional programming way, by passing in the original integer, and overwriting it at the same time. That goes something like this:

int ReturnFour(int copy){
copy=4;
return copy;
}

int anInt=3;
anInt=ReturnFour(anInt);
//anInt is now 4.

Okay so the example function is a little ridiculous, suspension of disbelief is required.

Since pointers are so useful for avoiding the “changing the copy not the original” accidents that sometimes happen, it can be too easy to not pay attention to when a pointer to a pointer should be passed into a function. Imagine a function that loads in a texture to a certain location in memory. If we give that function a pointer to an SDL_Texture, as an example, then it will write to the copy of the SDL_Texture pointer, and the original will retain it’s original value, hopefully NULL.

void LoadImage(std::string path, SDL_Texture* pTemp){
pTemp=LoadImageAt(path.c_str());
//pTemp stores the correct memory address, but…
}

SDL_Texture* pImg=NULL;
LoadImage(“C:\\…\\catDancing.png”, pImg);
//pImg is still NULL here.

Because we took a copy of the pointer, only the copy points to the correct location in memory of the image. This is a frustrating bug, because we don’t know we screwed up until we actually go to use the texture pointer, which might not be until the very opposite end of our code. In other words, things will appear to have loaded in just fine, but won’t work. The solution, is to either go functional, and return the copied SDL_Texture*, or just pass in a pointer to a pointer:

void LoadImage(const std::string path, SDL_Texture** ppImage){
*ppImage=LoadImageAt(path.c_str());
}

SDL_Texture* pImg=NULL;
LoadImage(“C:\\…\\catDancing.png”, &pImg);
//pImg is now correct.

In the second line, I’m using the address of the texture pointer, instead of manually creating a pointer to a pointer. Basically what I’m passing in is the memory address of a variable that points to the memory address of a texture, instead of just the variable that points to the memory address of a texture. This might sound confusing, but honestly it’s very simple, but being simple didn’t stop me from making this mistake in my initialization code, where I tried to set up the pointer to the renderer and the pointer to the window. Everything work initially, but since my pointers remained NULL, when I went to do anything with them the program crashed.

BUFFER OVERFLOW

I had a blog post I wrote up at the time detailing the crazy behaviour of my program when I had one of these. Basically, C and C++ give the user access to a data structure that is just the right size for the variable you’ve specified, multiplied by the amount of variables specified. It’s called an array, and it’s sequentially laid out in memory. If you have an array of 10 integers, then somewhere in memory there are (4 bytes per integer)*(10 integers)== 40 bytes of memory right next to each other that “house” those integers. There are a lot of benefits to this type of data structure, such as ease of set up, and speed on modern CPU’s with caching, however there is one major drawback. The programmer may accidentally write to past the end of the array, or have someone maliciously write past the boundaries of the array. In the latter case, that’s a way people use to hack code, and not really relevant to my game because there are benefits to having nobody play your game. In the former case, that’s a great way to cause your program to screw up badly.

Since the object I was writing to was allocated on the stack, instead of randomly in memory, I got a lot of very consistent, and very weird errors. Since I was overwriting quite far past the end of the array, I overwrote quite a bit of other things with essentially random data. What’s so interesting about the problem isn’t that things didn’t work, it’s the way in which they failed so weirdly. Here’s the video:

MEMORY DEALLOCATION ERRORS

There are two ways to get more memory for a program. The first, and easiest way, is to allocate the memory on the stack. That’s as simple as:

{
int someInt;
//do thing
}
//automatically deleted

The stack is a small bit of memory given to the program at runtime, usually between 1-10MB. Programs can also use the “heap” or “free store”, which is all the rest of the memory avaiable on the computer. The way to use the free store is:

int* pNewInt=new int();
//do thing
delete pNewInt;
}
//manually deleted.

I made the conscious decision to have all of my code be allocated on the stack, which made sense considering how tiny my program really was. The only code that was allocated on the stack, was the SDL2 textures, music clips and music files. The only thing I had to do was write something such as:

SDL_DestroyTexture(nameOfTexturePointer);

…and the memory would be freed up again. Needless to say, I forgot to do this sometimes, with the result being that my program was usually quite stable during a particular state, but would keep growing and growing the more the user flipped between states, such as going from in game to the menus and back. Some testing hunted all this down, but it was kind of shocking to see my program leap it’s way up Windows Task Manager 40MB’s at a time.

BAD MEMORY ACCESS ERRORS

This is kind of a catch-all term, but I’m using it to refer to the time, right at the end of the project, where I accidentally tried to access the -1 element of an array, which obviously doesn’t exist.

I had just implemented a very basic system that would show which turret arrangement the program was on and display this number at the top left of the screen. All went well until the user died, at which time I temporarily set the number to a negative. The number was only negative for one frame, but that meant that I was trying to render the corresponding digit, and there is no negative digit. Luckily the program just crashed there, instead of displaying crazy behaviour, and so I was able to handle the special cases of digits being negative by displaying 0. It was only up for one frame anyway.

COPY/PASTE ERRORS

This is not actually a specific type of error, more just a way to create errors. With better code design I would have had less repeated code, but as it was, I found myself copy-pasting code numerous times. Sometimes this was pretty much unavoidable, such as the loading code, which had to be slightly changed for each new texture I created. Everytime I would create a new texture I had to write something like:

SDL_Texture* /*pName*/=NULL;
if (!LoadTexture(tdcDirectoryPath+”\\Images\\Gameplay Images\\/*correctImage.png*/”, &/*pName*/, pFrame)){
std::cout << “Error loading /*name of image*/ image\n”;
return 1;
}

Everything that is put in /* */ needs to be changed for each specific iteration, which is the name of the SDL_Texture, and specific name of the png file need to be changed, as well as the error message given upon failure. I had on more than one occasion forgot to change one of those three, which leads to either overwriting a previous texture pointer, loading in the wrong image, or having a bizarre error message displayed.

The worst bug was when I copied and pasted some duplicate collision box and movement float arrays from one character to another character. The problem was that I copied arrays that were size 8, and didn’t change them to be size 64. This lead to the buffer overflow error detailed previously.

All in all, I feel that copy/paste errors are kind of a just punishment for bad code design, since you really shouldn’t be copy and pasting so much code in the first place.

MATH/TRIGONOMETRIC ERRORS

Math solutions are kind of insulting because the simplicity of the final solution often disguises the difficulty of getting there. I had a problem where I was trying to put the sword in the right place, and having it work properly when rotated. This was a hard problem that ended up being solved by:

atk.x = clBx.x+sin(angle/57.2957795)*PC_SIZE;
atk.y = clBx.y-cos(angle/57.2957795)*PC_SIZE;

The sword collision box is made to be the top left corner of the player character. Then we move it right by the proper amount, and down by the proper amount. The way we get the proper amount is by using the angle that the player is facing, and “pushing” it according to the sin of the angle in radians (hence the /57.296 conversion), multiplied by the length of the player character, since we always want it in the front of the character. Since sin is at it’s maximum at 90 and 270 degrees, or in our case, 90 and -90, we need sin for the x value, since if the character is looking straight forward or backwards, we aren’t going to be moving the sword at all in the x-axis. Cos is at it’s maximum at 0, and 180, or -179.999, which means we use that ratio to push the sword in the y-axis, because if the character is looking straight ahead or straight back, we want to push the sword the full amount forward or backwards. If that sounds confusing, partly it’s because I didn’t do a great job explaining it, but it really is kind of hard to solve. Once it’s solved, it seems trivially easy, the kind of problem that can be solved in two lines.

I also struggled to implement the hunters movement code. I wanted the hunters to maintain constant speed, but have a certain rate of acceleration that they would use to turn. So basically imagine them as heat seeking missiles that lasted forever. I couldn’t quite figure out how to do this, and had a number of buggy iterations that didn’t work. The solution again came down to two lines:

xVel[i]=sin(angle[i]/57.2957795)*HUNTER_DIS_PER_FRAME;
yVel[i]=cos(angle[i]/57.2957795)*HUNTER_DIS_PER_FRAME;

It’s funny to me how ridiculously simple this is. Of course, the .moveHunters() code is exactly 50 lines, so it’s not quite this simple, but it’s pretty close. All that’s missing really is the code where I find out what angle[i] should be.

API ERRORS

The worst error to have is one that you’re not responsible for, and don’t have access to the source code to fix. I’ve detailed this bug previously, but the short story is that I noticed that my code would crash very often, usually before 7 minutes. I tracked this down to the TTF_Fonts API I was using to render text to the screen for me. This made me panic a little bit, since I used this to display the time as well as to render the messages telling the player what to do onto the screen. In the end, I had no choice but to manually create the messages in Microsoft Paint, and then display the correct one manually. I also created a texture for every digit 0-9, and had a system where I figured out how to put the correct digit in the correct spot based on the time and manually put the time up. Extremely frustrating.

0 1 2 3 456789

I manually created these images in Microsoft Paint. It worked out pretty well.

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

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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