Skip to main content
GameDev.net gamedev.net
Using GameDev.net for your class this semester?
Learn more →
🔒 Locked

When you realize how dumb a bug is...

Started by Sik_the_hedgehog Oct 17, 2014 at 7:00 AM 152 replies 68.9k views
Original Post
Sik_the_hedgehog
Sik_the_hedgehog

Since some months ago we have been trying to hunt down some bug in my game. Basically, the invincibility theme got cut off early in gameplay, which hinted at a timing issue. The game was obviously taking up 1200 frames (20 seconds) as usual, so I wondered if the framerate system was failing on his (the musician's) system. First I reworked the framerate system so it literally stayed in sync with the timer instead of trying to count on its own, but that didn't work. I went as far as looking up hardware bugs (which I had assumed would be dead by now but I wanted to make sure) and trying to set the thread's affinity to avoid them. Nope.

...then I look at the OGG file again, just in case. It's 0.4 seconds longer than it should. Nobody noticed for months. *headdesk*

Don't pay much attention to "the hedgehog" in my nick, it's just because "Sik" was already taken =/ By the way, Sik is pronounced like seek, not like sick.
Glass_Knife
Glass_Knife

It is amazing to me how easy it is to get off on the wrong track and take so much time before you realize your mistake. But you didt the right thing: always assume it's your code. Except it wasn't. Damn.

I just went through this. Weird bug that could never happen. There is it, right on QA's screen. They were using an older version before the bug fix. Never even crossed my mind.

Orymus3
Orymus3

Happened to me today. Ran a video export simulation using dummy images. Transferred to a different computer to eliminate unknown inter-dependencies, and moved all folders along.

Didn't work.

Debug log didn't specify anything meaningful.

Was stressed.

Spent an hour fixing it to no avail.

Then, looking at all files I had copied over, I realized that though I had moved the 'Frames' folder from which I drafted the dummy images, it was somehow empty..........

Sik_the_hedgehog
Sik_the_hedgehog

Part 2

Composer was trying to test the WIP of one of the level themes and he complained that it played in the sound test but not in-game (!?). Then I checked myself and it worked on my end. Cue being completely clueless, especially since nothing at the code hinted at a possible bug. Some minutes later he makes a comment about the game and I realize he was making the theme for another level and because of that he was using the wrong filename (thereby the game of course not playing it).

Don't pay much attention to "the hedgehog" in my nick, it's just because "Sik" was already taken =/ By the way, Sik is pronounced like seek, not like sick.
Servant of the Lord
Servant of the Lord

I just went through this. Weird bug that could never happen. There is it, right on QA's screen. They were using an older version before the bug fix. Never even crossed my mind.

I do that myself occasionally.

Tweak -> build -> run and view changes
Tweak -> build -> run and view changes
Tweak -> run previous build accidentally -> wondering why the changes didn't take place -> starting reading the code to make sure I wrote it correctly

Sik_the_hedgehog
Sik_the_hedgehog

I lost the count of times I press build multiple times just to avoid that (I'd rather waste time building too many times than not build and go crazy figuring out what went wrong). Not really a big problem with C since Code::Blocks will just say it's already built, more of a thing with assemblers which will build the entire thing from scratch (but then again it's rather quick anyway).

EDIT: I suck at proofreading...

Don't pay much attention to "the hedgehog" in my nick, it's just because "Sik" was already taken =/ By the way, Sik is pronounced like seek, not like sick.
Krohm
Krohm

Reference data does not match data from new code.

Checked again, again, again and again.

Did I forgot an offset?

Reference data comes from a different project. It's basically a for(...) and I'm interested in a certain loop iteration.

In a certain loop iteration. Not in two different loops iterations. Changed iteration to debug to same value. Realized there was no problem to fix. Called it an intense day.

Previously "Krohm"
Khatharr
Khatharr

I do stuff like this more often than I'd like to admit. I'm actually trying to train myself to suspect resources sooner, since they're generally easier to check.

I did it in my recent course project, where there was a problem with my map file that was obscuring an oversight with my pathfinder, and then I just did it a couple days ago when I was fixing a bug in a KSP mod, but no matter what changes I made the game behavior wouldn't change. It turned out that the dll I kept dropping in the KSP folder didn't have the same name as the original, so I wasn't actually overwriting the correct file. -.-

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.
KuroSei
KuroSei

Exporting a tree-structure as a visual output to another tool from a tool that doesnt provide positional data...

So yeah... Calculate them from the structure. Not that hard to do, right?

But i wasted like a shitton of time because the target tool had the undocumented feature to set everything with a x or y coordinate of 0 (totally valid value...) to 100 / 100. Searched for ages in my code and then just tried adding 1 to everything... and suddenly it worked.

Biggest derp in my recent programming carreer. :/

Endurion
Endurion

You aren't a real programmer if you didn't have the AH! effect a few times.

It's once you find that nasty bug that has always eluded you.

In an older company I wrote a small tool that sat in the notification area. Once clicked it squealed like a pig and increased your personal score. It's quite relieving to hear a few squeaks every now and then :)

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>
Pether
Pether

Bullet::Bullet(..., Spritesheet *spritesheet, ...){
	this->spritesheet = spritesheet;
}

Spent a few hours on that. I wouldn't say the bug was dumb but more I that think I am too smart to do such errors. :)

Glass_Knife
Glass_Knife

You aren't a real programmer if you didn't have the AH! effect a few times.

It's once you find that nasty bug that has always eluded you.

In an older company I wrote a small tool that sat in the notification area. Once clicked it squealed like a pig and increased your personal score. It's quite relieving to hear a few squeaks every now and then smile.png

I read somewhere that the smaller the code change to fix a bug, the harder it is to find. Seems true.

swiftcoder
swiftcoder

I read somewhere that the smaller the code change to fix a bug, the harder it is to find. Seems true.

I keep a tally of all the bugs I have fixed with a single line code change. Over time it's reached a fairly horrifying number - those bugs seem to be the easiest to overlook in the first place as well.
Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]
slicer4ever
slicer4ever

You aren't a real programmer if you didn't have the AH! effect a few times.

It's once you find that nasty bug that has always eluded you.

In an older company I wrote a small tool that sat in the notification area. Once clicked it squealed like a pig and increased your personal score. It's quite relieving to hear a few squeaks every now and then smile.png

I read somewhere that the smaller the code change to fix a bug, the harder it is to find. Seems true.

indeed, for example about a week ago, i discovered this bug:


size_t Len = strlen(Text+1);

instead of:


size_t Len = strlen(Text)+1;

the worse part is this wasn't caught for probably 3 or 4 weeks since the module was built because i just kept getting lucky, and the data past the new text buffer just happened to be null, and the searchs would terminate normally.

21st Century Moose
21st Century Moose
indeed, for example about a week ago, i discovered this bug:

size_t Len = strlen(Text+1);

instead of:


size_t Len = strlen(Text)+1;

the worse part is this wasn't caught for probably 3 or 4 weeks since the module was built because i just kept getting lucky, and the data past the new text buffer just happened to be null, and the searchs would terminate normally.

I'm in the habit of always using array indexing instead of pointer arithmetic wherever possible for this exact reason. I'd never write "strlen (text + 1)" even if that was what I'd intended; it would always be "strlen (&text[1])" instead.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls. 
Servant of the Lord
Servant of the Lord

Bullet::Bullet(..., Spritesheet *spritesheet, ...){
	this->spritesheet = spritesheet;
}

Spent a few hours on that. I wouldn't say the bug was dumb but more I that think I am too smart to do such errors. smile.png

Where's the bug here? I'm not seeing it. Sure, it should've used the member-initializer list, but even so this should still work. 'spritesheet' is local to the function,

and thus gets priority, and then 'this->spritesheet' is explicitly specified, so it should compile correctly to: (class-member)spritesheet = (func-local)spritesheet;

What went wrong?

Ravyne
Ravyne

My "best" bug happened way back, in a compiled version of QuickBasic (4.5, for those who remember). I had well exceeded anything most bedroom QB coders had done in terms of volume/advanced (not to say I was genius, only that few people were content pushing QB rather than moving on to, say, C). Anyways, my source code had grown too large for the DOS-based editor to keep it all in memory, so I started writing code in windows using a programmers editor and a make-like build system someone in the QB community had written to solve this problem.

One day I had made a large changeset to convert my tile engine from a grown-too-large switch statement, to indexing my tiles using pointers into a big memory buffer -- sounds simple, but pointers weren't really a concept in QB originally, they had been added in v4.5 (or maybe v3.0), and it was also DOS 16bit pointers where you had to juggle code and data segments separately, in sync with whatever you were doing with pointers. I was maybe 14ish at the time, and I knew a little bit about 32bit pointers from C, but the segments/near/far pointers of DOS were new to me. This was Windows 95 era, so Windows at the time was still intimately connected with 16bit DOS in some ways, but was supposed to be isolated at least to the point that Windows would remain standing even if a DOS app crashed.

Whatever changes I had made that day proved the isolation theory wrong. I had introduced a bug that instantly blue-screened Windows, bringing down the whole computer. A proper debugger was an unknown luxury, so you guessed and checked your way to a solution, logging mileposts and conditions to a file, commenting out sections of code, or even by counting beeps (which was only scalable if you knew the ballpark your bug was in). I narrowed it down within an hour (several crash/reboot cycles later) to the lines of code that were setting up segments and pointers. There were a pair of lines repeated to set up the 4-5 segments of memory I was using and then compute the pointer within that, given an index. I narrowed it down to one of these pairs -- now, the pairs themselves were identical, save for which segment they were modifying and as I remember it the API was such that it couldn't be re-factored into a function, so I had just retyped the lines several times.

So I compare the lines in the pair to each other and everything lines up. I look at the pairs above and below, and each pair also lines up with each other. The surrounding pairs also work just swell. The program doesn't crash when I comment out the offending pair. I spend my evenings for 3-4 frustrating days researching segments, and pointers, theorizing, testing, failing -- wondering what could be causing the one pair to fail when the others worked. Everything lined up, or so I thought.

It turns out that every pair did line up, but the offending pair didn't line up with the working pairs in just one way. In the others I had done the pointer arithmetic correctly with an addition operator, and in the failing pair I had mistakenly transcribed a multiplication operator in its place. I didn't realize this until, as a last resort, I compared the pairing lines character by character with the preceding, working, pair. Days wasted. Fucking Eureka's lament. Wherever the pointer landed was somewhere in the weeds that Windows, or DOS, or something in between didn't much like.

throw table_exception("(? ???)? ? ???");
SmkViper
SmkViper




Bullet::Bullet(..., Spritesheet *spritesheet, ...){
	this->spritesheet = spritesheet;
}
Spent a few hours on that. I wouldn't say the bug was dumb but more I that think I am too smart to do such errors. smile.png



Where's the bug here? I'm not seeing it. Sure, it should've used the member-initializer list, but even so this should still work. 'spritesheet' is local to the function,
and thus gets priority, and then 'this->spritesheet' is explicitly specified, so it should compile correctly to: (class-member)spritesheet = (func-local)spritesheet;

What went wrong?



I'm guessing the original bug didn't have "this->", and adding it was the fix. So it would assign the parameter to itself.
Prototype
Prototype

I once spent hours figuring out why this loop started with random values:


for (int i=l; i<10; i++) {
 ...

That's why syntax coloring is useful.

Sacaldur
Sacaldur
I once did something (in JavaScript) like:
function Category() {
    //...
}
Category.prototype.entries = [];
And I wondered, why all elements created with "new Category()" contained the same entries.
As a hint, this one works:
function Category() {
    //...
    this.entries = [];
}

Since it was a test with a new framework (AngularJS), I almost started to blame the framework for not doing it right. It didn't took to long to figure it out, but it's still embarrassing...

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.