Dumbest Coding Mistake you've made?

I don't know if there's been a thread about this before, but I need something interesting to read for Friday and hopefully this will do it.

I'll start it off with my own dumbest coding mistake.

Back in the olden days when I was using VB a lot, probably in early highschool, I wrote a fairly long program with a lot of logic. All tightly coupled with the interface of course, but that's not the WTF, that's VB. I ended up with a few dozen loops, and in every function with a loop I had the classic "dim i as integer" (or something similar). All well and good, all things considered.

It eventually occurred to me that I could save a lot of trouble by declaring the loop variable as a global variable. Perfectly sensible! So I removed all the "dim i as integer" and stuck it at the top of the module.

The next time I tested my code (wasn't for awhile), I was getting all kinds of weird looping areas. It's pretty obvious that it was caused by functions inside loops that were screwing with the loop counter, but I didn't know that so I spent a significant amount of time debugging before I finally realized what I was doing and banged my head on the desk. D'oh!

I was writing my first PHP application using sessions, and I couldn't, for the life of me, get the link to show up that was to take me from the page that set data in the session to the page that displayed it. I seriously sat there and changed the session code for an hour or more before my roommate (who was thoroughly baked at the time) came into my room and immediately pointed out that my link code looked like this:

<a href="url/to/other/page"></a>

Yeah, I had forgotten to put anything INTO the anchor tag to click on. What the hell was I thinking?!?

I've never really made any huge coding mistakes as such, plenty of WTFs though.

The biggest one I can remember at the moment...

When I first started coding php/sql I wrote a program that gathered a few hundred records from a database and displayed them in a table. I hadn't coded for years and just threw it together without actually reading the manual properly. Instead of running a loop / array, I made 1 statement to grab every field of every row individually. Over 2500 sql statements nested in 2500 table cells. It coped surprisingly well for the few weeks it was implemented on an unbusy site. Then I learnt about grabbing entire rows and looping and suddenly 2499 of them disappeared.

A couple of months ago, I was working on some code for a Tmote Sky sensor that had to fire periodically. Since timing was important, I had to hook directly into the timer interrupt. With that in mind, I managed to cook up something like this (paraphrased from NesC code):

init() {

...

startTimer(interval)

...

}

timerFired() {

restartTimer(interval);

...

}

where interval is global to the module. (It's a NesC thing. Don't ask.) Wanna guess what happens when you forget to set the interval before initializing the component? (Hint: the interval defaults to 0.)

Debugging code like that without a JTAG can get really entertaining, since printing debug messages to the serial port won't work. Flushing the serial buffer has to be done outside of the timer interrupt handler, by which point you've already managed to destroy the stack.

When I went to University for the first time, I bought a book called "C++ For Dummys" and set to work trying to make things. After a lot of messing about and surfing the web I managed to get a nice little Uridium clone going. It was brilliant, it used mode 13h graphics, had a scrolling tile map background, a level editor, all sorts of flashy stuff. But for some reason it would keep crashing at random intervals, for no apparent reason. This was before I understood how to use debuggers so I was still using the cout << "The program is here!" method of debugging but to no avail.

There was no seeming pattern to the crash, a piece of code would run a thousand times without crashing, before suddenly exploding whilst doing something which as far as I could tell was a perfectly valid operation. This whole problem was compounded by the fact that I was using windows 95, and every time the program crashed I'd get a warning telling me I'd probably damaged the run time state of the OS in some way and should restart my machine. After almost a month of totally fruitless debugging and tweaking, I had a revelation while re-reading the chapter on using strings in C. I'd gotten used to reading things like:

const char myString="Hello world!";

and had gotten it into my head that "char" was a perfectly good storage object for a string. After going through the code and removing all the pieces that looked like:

UPDATE jobcontrol SET status='3' WHERE status in ('1', '2', '4') AND seqno BETWEEN ? AND ?

...instead read:

UPDATE jobcontrol SET status='3' WHERE seqno BETWEEN ? AND ?

This being a batch job queue, and status 1, 2 and 4 being various "waiting to execute" states, this took jobs in other states (post-execution or post-failure, plus cancelled and holding states) and the result was the same job running over and over and over and over and over and...

UPDATE jobcontrol SET status='3' WHERE status in ('1', '2', '4') AND seqno BETWEEN ? AND ?

...instead read:

UPDATE jobcontrol SET status='3' WHERE seqno BETWEEN ? AND ?

This being a batch job queue, and status 1, 2 and 4 being various "waiting to execute" states, this took jobs in other states (post-execution or post-failure, plus cancelled and holding states) and the result was the same job running over and over and over and over and over and...

This is the cousin of the classic UPDATE or DELETE statement with the forgotten WHERE clause. Who hasn't done that one?

I'm not really sure of a good WTF. I'm sure there is plenty in my coding history. At one point I was doing some GBA development and neglected to hook up a gcc compiler for arm7tdmi to visual studio 6. The GBA has a lot of memory registers that are commonly referenced with lines such as:

#define REG_DISPSTAT *(volatile u16*)0x4000004 //Display Status

there are usually about a hundred of these that you commonly use to do any number of things such as flipping/rotation of sprites, keypad input, loading tilemaps, changing display mode, etc. Basically everything. needless to say then end result of running this code as windows console app was pretty amusing.

This is the cousin of the classic UPDATE or DELETE statement with the forgotten WHERE clause. Who hasn't done that one?

I could almost say I haven't, if it wasn't for Microsoft's SQL Server Management Studio. Apparently, if you highlight part of a query, it only executes that part. I had just pasted in "DELETE * FROM ImportantTable" into a query that ended " WHERE Row IS NOT THAT IMPORTANT". Unfortunately, having just pasted it in, only the delete clause was selected when I ran the query...

I was going throgh some code from my first programming job the other day. I used Visual Basic 6 and needed to store some variables in an INI file. I spent a few hours writing a function to read the entire INI file into a string, seeked to the position where the variable was stored and returned the value that was called. The same thing for saving to the INI file. It never occured to me that maybe, just maybe, this had been done before. Perhaps the nice people at Microsoft might have even included it in an API or something. They might have called it GetPrivateProfileString...?

I've had plenty of while loops without incrementing the counter, so they just ran forever, but I think my dumbest wasn't precisely a coding mistake. I set up a backup for a large database, and set it to add to the backup set, instead of overwriting. It was backing up to the same hard drive as the database. It was backing up every 4 hours. Needless to say, in less than a week, that hard drive was crashing regularly because it was a little bit on the overful side.

When I was in college I was taking a course in Unix System Programming. We had an assignment to implement some kind of simple client-server task; the server program would run on one machine, the client on another. It was pretty basic, I think it just sent a command (like ls -li or grep somethingorother) from the client to the server, who would execute it and then send the result back.

I usually did my coursework from home by telnetting onto the unix servers.

So anyway, the server was implemented by running in an infinite loop and waiting for a connection from the client. On one early attempt, I did something wrong and the program failed and got stuck in an infinite loop of displaying whatever error message on the telnet screen and also writing a message to a logfile.

I was unable to exit the program, so I just closed the terminal window and logged back in a minute later. I didn't know this, but the process was still running, of course. I didn't see it when I ran a ps command (I wasn't versed enough to know to try ps -ef | grep myloginname ) So, the process continued to run and I soon started getting 'disk quota full' warnings.

Then for a few hours, I was unable to connect or log on at all.

A little later, everything was back to normal again. I never heard anything about it afterwards, but I was a little more careful about testing future versions.

In university I took a course called real-time in which groups of two would build a microkernel OS along with drivers and services and an application, loaded via GRUB, from the ground up. My partner and I both did some pretty crazy stuff to get the job done in time, but these two are our individual best:

I was in charge of writing the kernel trap; that is to say I had to write the ASM sequence that context switched from a running application into the kernel. Most of the time this was accomplished via a call to certain C functions which were just masks for this trap. This was before I understood how GCC handles parameter passing. I knew that GCC pushed the parameters onto the stack, and I knew the order in which they are pushed, so as part of the context switch I popped them off to take a look at them. The problem is I assumed that GCC expects functions to pop off their own parameters from the stack. Boy was I wrong. We got the strangest errors from user processes because of these "stack hacks", as my partner called them. It took us about an hour to figure out that GCC doesn't want the called method to pop its parameters, and that the caller is what, in fact, pops them.

His biggest WTF was considerably more damaging and harder to track down. We had written two different text output libraries: one for debug in a special colour that required a #define to work, and one for normal user process output. As you know, VGA occupies RAM addresses before the 64KB mark (0xFA00 - 0xFFFF if I recall correctly). GRUB loads the kernel immediately at the 64KB mark. The contents of those RAM addresses are displayed on the monitor. There are about 25 displayable lines in that space, and we used simple looping when the line got down too far, to come back to the top. Well, we noticed that when we ran the application without debugging, it worked fine, but when we turned debugging on, the craziest stuff would happen. After about four hours of trying to figure out why (though I'm sure you can guess why by now), I noticed that he had written his looping algorithm with if (line == 25) { } instead of if (line > 25) { } for regular messages. Then I checked out debugging messages. I found if (line == 24) { }. As I'm sure you can guess, if debugging messages and regular messages came to the kernel in the correct sequence, the guard conditions would be skipped and further output would be written past the 64KB address, directly on top of the kernel. Strange things happen when the kernel is overwritten, let me tell you. Needless to say, after this incident I was in charge of writing our remaining I/O libraries.

In university I took a course called real-time in which groups of two would build a microkernel OS along with drivers and services and an application, loaded via GRUB, from the ground up. My partner and I both did some pretty crazy stuff to get the job done in time, but these two are our individual best:

I was in charge of writing the kernel trap; that is to say I had to write the ASM sequence that context switched from a running application into the kernel. Most of the time this was accomplished via a call to certain C functions which were just masks for this trap. This was before I understood how GCC handles parameter passing. I knew that GCC pushed the parameters onto the stack, and I knew the order in which they are pushed, so as part of the context switch I popped them off to take a look at them. The problem is I assumed that GCC expects functions to pop off their own parameters from the stack. Boy was I wrong. We got the strangest errors from user processes because of these "stack hacks", as my partner called them. It took us about an hour to figure out that GCC doesn't want the called method to pop its parameters, and that the caller is what, in fact, pops them.

That's not GCC, its the cdecl calling convention, used by most C/UNIX systems. (Except Windows of course...).

My Intro to UNIX class, we had to write a shell script to do a merge sort of a large file by splitting it into smaller files, etc etc.

Where was the best place to store these files while working? /tmp? never! /users/vt_mruhlin!

Once I finished coding, I grabbed the sample file and began runnning it. It took a few seconds, but I waited patiently. It was a big file, after all. About 20 minutes later, I asked the TA how long it should take to run. "Oh, about 2 seconds". Hmmm.

My home directory was full of so many tiny little files that I couldn't even try to delete them without the rm command throwing some crazy errors. I said screw it and left the files there.

This is the cousin of the classic UPDATE or DELETE statement with the forgotten WHERE clause. Who hasn't done that one?

I've done an indiscriminate UPDATE on the mysql.db table of a really, really, really busy database server one day, while working to fix another mistake I had hoped my boss wouldn't notice.

Amazingly, I actually had it all working again within another thirty seconds, and nobody ever noticed. But gosh, I think I aged a year in those thirty seconds.

Since then, I have an irrational fear when using UPDATE or DELETE; and I usually type UPPDATE or DELLETE just to make sure it can't run prematurely, then only correct the spelling once the WHERE clause is in place.

One of my personal favorites was a combination of my screw-up combined with the ineptitude of the MySQL programmers. A few years back I wrote a system using MySQL 3.23 and I didn't validate my sql 100%. I essentially sent the following to the database:

Update Blah Set MyField = 1 / 0 Where Id = 1234

Guess what, it not only updated MyField to 0 instead of throwing an error, but set all rows to 0 for that column. Yeah, that was a fun error to trace and fix as it didn't happen that often.

This is the cousin of the classic UPDATE or DELETE statement with the forgotten WHERE clause. Who hasn't done that one?

I've done an indiscriminate UPDATE on the mysql.db table of a really, really, really busy database server one day, while working to fix another mistake I had hoped my boss wouldn't notice.

Amazingly, I actually had it all working again within another thirty seconds, and nobody ever noticed. But gosh, I think I aged a year in those thirty seconds.

Since then, I have an irrational fear when using UPDATE or DELETE; and I usually type UPPDATE or DELLETE just to make sure it can't run prematurely, then only correct the spelling once the WHERE clause is in place.

Agreed. I usually either run all queries first on a devel. machine, or I type the WHERE clause first, and then go back to the rest. Of course, one ought to just use BEGIN...COMMIT to be safe. The other way to really mess up is to accidentally type a semi-colon instead of a comma.

That's not GCC, its the cdecl calling convention, used by most C/UNIX systems. (Except Windows of course...).

Like I said, it makes perfect sense to me now. It's just that back then it wasn't something we were even taught, and so I was left to my own assumptions. It taught me never to assume anything, since my assumptions could be very wrong. It's a lesson I hope to never forget.

That's not GCC, its the cdecl calling convention, used by most C/UNIX systems. (Except Windows of course...).

More precisely, it's the SysV ABI for i386, used by everything that runs on i386-derived processors and attempts to be binary-compatible with System V UNIX.

If you're writing a kernel and don't desire binary-compatibility, you can (and may wish to) build gcc and the rest of the toolchain for a different ABI. SysV/i386 isn't the best way, it's just the traditional way.

When i started with PHP/MySQL i was annoyed by always having to write:

$sql = "SELECT thing FROM place WHERE foo = bar";

$query = mysql_query($sql);

$item = mysql_select_result(PHP's params here);

echo $item;

So wrote me a nice function that took an SQL statement and returned the column specified (my_mysql_query($query, $col)). Great, until it slowly dawned on me that every item i used from the DB was a single SQL query...

"Why does the connection NEVER work? I made sure I set the variables, I put a Debug.Print in NewInstance to check the variable, and it works when I set it in NewInstance. But never when I set it in Form_Load!"

Then I figured out that I was setting it after the call to NewInstance was made.