Sign in to follow this  
Lil_Lloyd

Your Worst "Gotchas" ever in programming

Recommended Posts

Lil_Lloyd    287

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?

 

 

Share this post


Link to post
Share on other sites
Waterlimon    4398

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

Share this post


Link to post
Share on other sites
Xanather    782

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.

Share this post


Link to post
Share on other sites
swiftcoder    18432

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.

Share this post


Link to post
Share on other sites
MilchoPenchev    1178

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.

Share this post


Link to post
Share on other sites
Helo7777    693

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.

Share this post


Link to post
Share on other sites
Ravyne    14300
  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.

Share this post


Link to post
Share on other sites
PurpleAmethyst    335

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.
 

Share this post


Link to post
Share on other sites
smr    2468

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

Share this post


Link to post
Share on other sites
Barbossa    967

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...

Share this post


Link to post
Share on other sites
HelloSkitty    152
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.

Share this post


Link to post
Share on other sites
Krohm    5030

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.

Share this post


Link to post
Share on other sites
TheChubu    9450

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.

Share this post


Link to post
Share on other sites
szecs    2990
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

Share this post


Link to post
Share on other sites
mikeman    2942

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)

Share this post


Link to post
Share on other sites
dave j    681
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".

Share this post


Link to post
Share on other sites
Josip Mati?    1304

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...

Share this post


Link to post
Share on other sites
frob    44908

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.

Share this post


Link to post
Share on other sites
_the_phantom_    11250

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...)

Share this post


Link to post
Share on other sites
_the_phantom_    11250

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 :)

Share this post


Link to post
Share on other sites
Pthalicus    738

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.

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