• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Lil_Lloyd

Your Worst "Gotchas" ever in programming

69 posts in this topic

Ever had an issue you just couldn't debug? You tried stepping through the program and the relevant parts line by line and the values in your watch window look ok, but the magic just isn't happening when you hit 'run'. You spend hours these problems, and then when you relax and take a bath or a walk the Archimedes moment happens and you realise the small mistake you made.

 

As for me I was trying to implement interleaved array buffer objects in Open GL today, and the meshes were rendering but the texturing just wasn't happening. After some careful deliberation and many attempts over a few hours, I gave up. When I was walking to my local restaurant I realised I didn't call glEnableVertexAttribute(). I get home, try it and it runs! 

 

So, time wasted or a lesson well learned? 

 

What are your most frustrating problems that were solved with something simple you forgot?

 

 

0

Share this post


Link to post
Share on other sites

Cant recall anything very interesting, but the latest ones were forgetting to make a function return a reference instead of a value (and assuming assigning an object to a reference would change where the reference points) and trying to figure out why my game always renders the cells in the middle of the screen as "loaded" (with chunked terrain) instead of the ones at the origin, because i forgot that of course the chunks will be loaded around where you are looking and not around the origin xP

0

Share this post


Link to post
Share on other sites

lol yes, I remember a few times actually where I wanted something to happen, and it didn't. Spent a while trying to debug it, and it was as simple as calling the method.

0

Share this post


Link to post
Share on other sites

Pass-by-reference can be a killer:

  • Neglecting to pass an argument by reference, and then staring at a profile trace where 75% of the time was spent in a copy constructor.
  • Passing by reference the nodes in a recursive-descent parser, which caused the same instance to be modified over and over again, and the parse to get stuck in loops.
0

Share this post


Link to post
Share on other sites

This took me back about 4 years, when I was working on my capstone uni project. Me and a friend were getting linker errors - something along the lines of " somevariable already defined in somefile.obj". No compilation errors - all our headers were #ifndef guarded, so we were scratching our heads for near four days.

 

The obvious thing, in retrospect, is that #ifndef guards only stop code declaration from happening twice. If you (as we did) put actual data in a header file (say, something like int someCount; that is not static), it doesn't matter if the .h file is guarded, when its included multiple times the linker will try allocate the variable again, and will fail, giving an error like above.

 

Bottom line is don't put anything except declarations in your header.

0

Share this post


Link to post
Share on other sites

Best one I've seen is a program missing the '()' when calling glEnd. Caused BSOD! Took a while to figure out till we realized we overlooked something as simple as some brackets haha.

0

Share this post


Link to post
Share on other sites
  1. Template meta-programming. 'nuff said.
  2. Deciding to do a small project in C, and forgetting all locals must be declared *before* any code statements in a scope.
  3. I once was doing some pointer arithmetic in Quickbasic, and my program, a 16bit DOS app, would crash windows entirely. I narrowed the problem down to one of four identical lines. It turns out that in one of those lines, in one place, I multiplied the pointer by some value, rather than adding. I have no idea what that caused it to overwrite, but I take crashing windows from a supposedly-isolated DOS app to be a point of pride.
0

Share this post


Link to post
Share on other sites

Colleagues who think that writing their own custom C++ string classes rather than using a well tested library is wise.

Missing or misplaced commas and brackets - I have spent half days utterly confused by these stupid mistakes that I made, every coder no matter how experienced has done this at some point.
 

0

Share this post


Link to post
Share on other sites

This:

 

>>>import time
>>> def report(when=time.time()):
...     print when
...
>>> report()
1210294387.19
>>> time.sleep(5)
>>> report()
1210294387.19

 

Python default arguments are defined when the function is defined, not when it's called. Calling report will always return the same value with no arguments. (I took this specific example from stackoverflow, but it's bitten me a few times).

 

Or you can get caught by it this way:

 


>>> class Thing:
...     def __init__(self, v):
...             self.v = v
... 
>>> def foo(thing=Thing(0)):
...     thing.v += 1
...     return thing.v
... 
>>> foo()
1
>>> foo()
2

 

 

 

A contrived in Oracle SQL:

 

SELECT * FROM table WHERE null != null

 

Will always return zero results because null is never equal or inequal to anything. In Oracle, varchar fields are never empty. They either have something in them, or they are null. Zero-length strings are considered null.

 

This means that the query:

SELECT * FROM TABLE WHERE COLUMN1 != 'THIS'

 

Will not return any rows where COLUMN1 is empty. The natural expectation would be that when COLUMN1 has no value, then it would not be equal to 'THIS' and thus would be included in the resultset. At least that seems natural to me.

 

The workaround:

SELECT * FROM TABLE WHERE COLUMN1 IS NULL OR COLUMN1 != 'THIS'
-- OR YOU COULD DO
SELECT * FROM TABLE WHERE NVL(COLUMN1, 'SOME-IMPOSSIBLE-VALUE') != 'THIS'
Edited by smr
0

Share this post


Link to post
Share on other sites

Last month I needed to access single characters from Delphi Strings. But whatever I did my program just put out trash and crashed.

After six hours (and almost implementing a replacement system) I got it:

While arrays start by zero, Strings in Delphi start at 1. So i kept interpreting the first byte, which does totally mess up Unicode....

 

Additionally in another project (GCC/Linux => C++) there was a function, log(), which compiled properly, but the linker never found it, whatever I try. (Multiple Headers, directly in the source file etc). Hours later I finally found an answer: The function was declared as

inline void Log( Ogre::String MSG );

In VC++ this works fine, but under GCC/Linux the "inline" caused the linker to search the function without finding it. Wasted way too much hours searching mistakes like that...

0

Share this post


Link to post
Share on other sites
I once had a school project in java dealing with Strings. Well, what better name for a class dealing with a project centered on Strings than String.java? Then when I tried to use methods of java's String class, the methods weren't there (because the compiler was trying to find the methods in my String class). Took two days to figure it out and it was only because I tried to rewrite the thing with more descriptive class and variable names after being inspired by a daily WTF article.
0

Share this post


Link to post
Share on other sites

Implementing a compiler front-end in Python. Write the prosaically-named 'SyntaxError' exception class. Realise that none of the methods on my SyntaxError class are accessible.

 

A little later, run 'pydoc SyntaxError' and realise the problem...

0

Share this post


Link to post
Share on other sites

I don't recall the best.

But I'll tell you what I just fixed.

 

Updated an old project to new interface.

It failed on a custom string comparison.

Figured out the new project had optimizations all ON while dependencies didn't.

0

Share this post


Link to post
Share on other sites

First time I used a treeset with a custom comparator and I couldn't figure out why it was loosing elements after calling sort().

0

Share this post


Link to post
Share on other sites

Probably everything when I'm kinda sleepy.

 

When I'm doing something and I'm not pretty focused, sometimes I go into "auto mode" and I eventually just lose track of what I'm trying to do and how.

 

So I code, code, code then something doesn't works and I spend 40min trying to figure out what I was doing (like literally, just trying to understand what I was doing the last 20 seconds), why, how I tried to do it and only then why it isn't working.

0

Share this post


Link to post
Share on other sites
Not calling the function I was debugging (and that was good for the first time and all along).

EDIT: I'm into some of those moments with Labview too. It's inherently parallel, so I'm sucking with queues and notifiers to avoid race conditions, sucking with messages getting lost and making workarounds to solve that.

Ah, yup, here's a gotcha: in Labview you draw wires (data flow) between icons (kinda like functions). I was debugging a bug for three hours, foaming at the mouth, breaking the keyboard in rage, when I accidentally noticed that the wire was hiding under the debugged construct (a case structure), and the wires from inside the case construct weren't actually connected with the outside. No wonder why values never changed. It was impossible to tell by eye, the wires where collinear, the little output "ports" were there on the structure, but not connected with the wire outside. Edited by szecs
0

Share this post


Link to post
Share on other sites

Yeah, I actually had one of these moments today...I implemented 3D sound with OpenAL, however it was clear to me that it didn't sound exactly right; like sounds switching from left ear to right ear randomly. I didn't manage to find what was wrong, so I closed the computer and went out...and on the cafe, I realized that AL_ORIENTATION would require 2 vectors, direction+upvector...just direction isn't logically enough no matter the API...so I returned home and sure enough, it expects 2 vectors instead of just the 1 I passed. Which, in OpenAL's C world means it expects a pointer to a 6-float array, which means it was just reading garbage for the up-vector. Don't you just love these kind of bugs?(OTOH, maybe I should have read the documentation more carefully :P)

0

Share this post


Link to post
Share on other sites
Not one of mine but a former colleague's. I used to work on an OS written in BCPL. BCPL calls a function named TIDYUP when an application exits. If you define your own, it calls that rather than the default one. (Think of it as a bit like an automatically registered atexit function in C). My colleague spent a day and a half pulling his hair out trying to find why his TIDYUP function didn't seem to be called. Eventually he gave up and asked someone for help. The other guy took one look at his screen and said "It's because you've spelled it TIDUP".
0

Share this post


Link to post
Share on other sites

My experience isn't interesting but is the only one I remember...

 

During last summer, when I started working on current project, at one moment I was implementing first collidable object. That time for tank I was using Vector2 Position and Vector2 Origin to tell spritebatch where to draw the sprite of the tank while keeping its bounding box as Rectangle. To be able to properly rotate tank, Origin must be set at the center of the texture itself. Position of tank was set the same as topleft point of its bounding box. I spent one week trying to figure out why was half of the tank going under the wall before eventually leaving it out of burnout and frustration.

 

2 months later, I remembered that Origin defines the point from which the sprite will be drawn...

0

Share this post


Link to post
Share on other sites

Debuggers not being trustworthy is a big problem.  This is especially true for people working on new game consoles.  Whenever a fancy new devkit comes along there are always times when the debugger will outright lie to you about the state of the hardware.  Also on new systems you will run across occasional compiler and optimizer bugs.  This can require extensive debugging at the assembly level, taking great care to ensure values were not optimized out, or moved to another area, or otherwise behaving in a rational but unexpected way.

 

It can take a lot of work, and when you finally do get the 'a-ha' moment discovering that it is a debugger or compiler error, you then get the follow-up event of how to work around it.

 

 

Hardware bugs.  They can happen with bad firmwares, or inconsistent documentation where it really isn't a bug, just an undocumented feature.  They happen more often when the processors get very hot.  That's exactly what happens during games with compute-intensive processing and gamers with overclocked chips.  Several games, like GuildWars, take steps to detect and notify users when it occurs.

 

These also happen on early firmwares of game consoles.  Since they are covered under NDA you don't often hear the horror stories.  When you have documentation that says a function does something, and it doesn't do it, you must spend hours trying to figure out if it is your code doing the wrong thing, or if it is the black box doing the wrong thing.  Then you wait for the next firmware update and hope your problem is fixed.

 

 

 

As for the general problems, I've seen all kinds of things:  

 

Metaprogramming is just plain painful, don't submit it to the codebase.  Not only are there 'gotchas' all over the place, they fail spectacularly on data-driven development.  If you need to calculate Fibonacci numbers that are known at runtime, go ahead.  Otherwise either create a data table of pre-computed values or compute it at runtime.

 

Badly formed macros (#define) that include sequence points or don't properly place things in parenthesis, or even worse include complete statements, can be a source of frustration.  They are not expanded in the debugger, are not type safe, and just cause extra work.  I've spent many hours going through macro bugs.

 

Nested macros, especially nested macros that build complex structures should be avoided.  While it may be nice to have a few macros that convert a long list of labels into an enum, a corresponding string table listing the enum names, and a corresponding automatic registration at game startup, and so on... those macros really are a bad idea.  When they are fully debugged and have been used for several years they can be moderately useful, but there is a high cost to making them work correctly.

0

Share this post


Link to post
Share on other sites

Earlier today, while copying code from our old texture processing tool to the shiny new C# & C++/CLI hybrid I'd been making I was surprised when previously working code to parse a DDS file was no longer working correctly.

 

The code was a direct copy & paste job and the DDS was a known working one.

Debugger gave garbage for the DDS entries, yet looking at the source file in the hex editor everything checked out.

 

Old tool was 32bit.

New tool was 64bit.

DDS structure the code used had a void* hidden in it.

Data alignment hilarity ensured. 

 

*sigh* That's a few hours of my life I won't get back...

 

(Aside note: If you copy data into a System.IO.MemoryStream object make sure you seek back to 0 again or you can't copy that data back out as it is EOF : that one only took me a minute to figure out...)

0

Share this post


Link to post
Share on other sites

Debuggers not being trustworthy is a big problem.  This is especially true for people working on new game consoles.  

 

Annoyingly not just new consoles; back in 2008 I was working on a PS2 game (using good old Codewarrior!) and my team leader called me over as he was having problems with a function which seemed to be working yet in a debug session a variable was clearly not showing anywhere near the correct value.

 

It was near the end of the day so I only quickly looked it over before he went home but I could see nothing wrong in the code.

 

I get in the next morning around 10am to find him, our lead and another senior programmer all staring at his monitor trying to figure out what is going on. I join them and for a while, when another programmer joined us, it had 5 of us looking at it all puzzled.

 

After a while they started looking at the assembly level at which point I took myself away to read over the PS2 assembly docs, as I didn't know it at that point, before returning to the collection of programmers and looking over the code.

 

After about 10mins and some heavy thinking I declared I had figured it out - the compiler, despite being in debug mode, had decided to optimise away the assignment to the variable, instead keeping it in a register to pass directly to the next function call. The debugger, on the other hand, was blissfully unaware of this fact and carried on regardless.

 

Net result; panic disappeared and my estimation went up in the eyes of our lead significantly (at this point I'd only been at the company about a month) so much so that he a) trusted me with some large refinements to our scripting system and b) often requested me on projects after that as he knew I knew my stuff :D

 

In fact that's not a bad tip for new people; do something to get yourself noticed when you join somewhere. Raising your stock early on is a very good move :)

0

Share this post


Link to post
Share on other sites

Just a quick addition, since I have little time.

 

Symptom code:

int i = 0;

printf( "i = %d", i );

 

Output:

"i = 1"

 

It took four senior coders to work out what was going wrong here. The issue was overflowing buffers -> memory corruption. Causing data to not be assigned the value it was assigned. That was a fun monday morning.

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0