Everything I've ever written. It's awful. Don't look at it. Any of it.
You've seen things people wouldn't believe – so tell us your programming horrors
Shellshock. Heartbleed. That CCTV storage firmware with a hardcoded password. We've all seen some really bad code. Maybe that's just me. Given that many of our sysadmin readers have poured in tales of fixing impossibly broken servers for our On-Call series, we know our software-wrangling readers have faced similar battles …
COMMENTS
-
-
-
-
Friday 29th January 2016 11:47 GMT tfewster
> What are the other 11 steps?
There's probably a library of books and websites devoted to this, but in my experience:
Step 2: As noted by other commentards, leaving a comment saying "Kludge" or similar; Bonus points for pointing out situations where it will fail.
Step 3: A comment describing what you're actually trying to achieve; Best case, someone else will know how to fix it; Worst case, it will help you with Rubber Duck debugging. Nowadays I usually start by writing pseudocode anyway, so the comments are already in place.
Step 4: Review your assumptions: Will this code definitely be rewritten/replaced/binned before Y2K? Will it scale [so `if (a ~b)` doesn't come back to bite you when b > 9]?
(Step 1.5 should probably be "Don't call your variables 'a' and 'b' ")
Step 5:???
(Obligatory Step 6: PROFIT!!!)
-
Friday 29th January 2016 12:13 GMT BongoJoe
(Step 1.5 should probably be "Don't call your variables 'a' and 'b' ")
Ah, but there is, or was, a time when it was worthwhile to do so.
Many years ago I wrote code onto Hollorith Cards and if you recall these then there's basically one line of code per punched card. Sometimes the ladies in the card punch room would fail to read my handwriting on the coding form and type something slightly different.
And if this was the case then one had to find the card and replace it with one of one's own. Now there was a number of options available. The first was to go and put through the single card required through the system which could take a day or so (and the single card may get lost between the punch card room and oneself).
The second option was to go into an auxiliary room with a crufty old machine that one could stamp out the card for oneself. This option meant moving off one's arse and to use a machine which was, effectively, running off three phase mains with cloth covered mains cable and the machine, because the girls wouldn't touch it, would be a heath hazard. And in the 70s a Health Hazard was really a Health Hazard.
The third option was Cut And Paste. Seventies style.
If one purposely didn't use descriptive variables and just stuck to the likes of x and y then it would be simple enough to find a card from another application, borrow that and shove it into one's card stack in the right place.
Which really had a number of side effects. First this didn't lend itself to good naming conventions (which didn't exist in those days anyway) and, secondly, if one forgot or didn't even know that your code was tampered with then the debugging became a real nightmare.
Hollorith cards. That was real programming. Especially if carrying the deck of cards to the machine room and they fell out of their elastic band and spilled all over the floor requiring a massive sort run manually...
-
Friday 29th January 2016 17:41 GMT Brewster's Angle Grinder
>(Step 1.5 should probably be "Don't call your variables 'a' and 'b' ")
The first BASIC interpreter I used only paid attention to the first two characters of a variable's name. So the variables
STRENGTH
andSTUPIDITY
were both handles to the variableST
. For that reason, it was considered good practice to only give your variables two letter names so as to avoid unintended collisions.Even today, Chrome decides to inline based on the length of the text in a javascript function. But obviously, good practice is to minify.
-
-
Monday 1st February 2016 12:28 GMT Brewster's Angle Grinder
IIRC, Commodore BASIC as used on the Vic 20 and C64 had that first two character approach - though probably not the only version.
Right era. Difference device. This interpreter was written by a company based in Redmond -- giving me early warning of what to expect. All numbers were treated as floats, too, so performance was terrible; but it spurred me into learning asm.
-
-
-
Saturday 30th January 2016 11:54 GMT David Roberts
80 colum cards
Firstly you should have a hand punch with lots of 3 key combinations for one off cards - this makes it relatively easy to replace a defective card.
Secondly if you can't be arsed to punch a whole new card you just fish a chard out of the punch and block up the incorrect hole by rubbing the chard in with a soft pencil prior to punching the correct hole(s).
Thirdly you always mark up the card deck with thick diagonal lines from a board marker so you can get them (almost) back in order by eye.
Tcah. Kids of today.......
-
-
Monday 1st February 2016 18:43 GMT Number6
Step 3: A comment describing what you're actually trying to achieve; Best case, someone else will know how to fix it;
I often put assumptions in the comments. "At this point x, y, z should be the case" "Assumes argument non zero" or whatever. Sometimes it's because I want to go back and put in the error checking once I've verified that I'm on the correct track (i.e. go write it properly second time). This helps with debugging and hopefully provides some level of documentation for the poor sod who has to fix or upgrade it once I've moved on. Fond memories of spherical geometry and a few short cuts and assumptions based on the real world usage of the code here.
-
-
Thursday 28th January 2016 23:18 GMT Anonymous Coward
I've tried to get better but then in previous jobs I was working on code written by a dead man for a database that stopped being supported 10 years prior. (using asp and a foxpro db)
Oh how we laughed when the accounts system died again because 1gb databases aren't actually that big...
That and stored procedures are the Devils work (or at least that was the impression given that no data manipulation was ever done in sql until I started working on it).
-
-
-
Thursday 28th January 2016 15:39 GMT caffeine addict
The worst bit of impenetrable code I found recently was some 10 year old PHP that was mess of procedural code in classes, with meaningless variable names and recursive functions that sometimes took variables by reference, and sometimes didn't.
The comments block just contained an apology to anyone who came to investigate it. Signed by me.
I've stopped judging any code that's more than a year old...
Still, at least I wasn't responsible for the code that tried to connect to a server 3 times before giving up. But which auto-incremented the wrong number, causing a cascade of unresponsive servers DOSing each other...
-
Thursday 28th January 2016 15:48 GMT apepper
My "favourite" bug was in Z80 assembler; I'd written a subroutine which converted a string to upper case. Our strings had a two byte length followed by the actual characters, so the routine looked something like this (pseudo code).
toupper: ld len,(hl) ' get the length
inc hl
inc hl ' skip the length
toupper1:ld a,(hl)
cmp a,'a'
jlt isupper ' if not lower case
cmp a,'z'
jgt isupper ' not lower case
' must be lower case
sub a,('a'-'A') ' convert that character
ld (hl),a
inc hl
dec len
cmp len,0
jne toupper1 ' more to do...
ret
The routine worked fine until someone passed a zero length string to the routine; then because the code decremented the length before comparing it with 0 to see if we'd finished, the routine converted the entire 64k memory - including the code - to upper case. By chance, a lot of stuff carried on working, so it took a couple of hours to to realize what was happening.
-
Thursday 28th January 2016 16:36 GMT Phil O'Sophical
I remember something similar in a VMS Fortran program. VAXen had a block move instruction, somewhat similar in operation to the C memcpy() function. Someone (I think it might have been me, but I can't remember) got the source & destination addresses backwards. Instead of rotating a buffer by 4 bytes when that line was reached, it shifted the whole program address space *except* the buffer by 4 bytes. Neeedless to say the program crashed almost immediately, but the resultant stack trace was incomprehensible, since everything was 4 bytes off. It took ages to figure out what was happening.
-
Friday 29th January 2016 04:35 GMT Peter X
Re: Lower to uppercase
I appreciate that was probably very old code... but you do realise that changing case in ASCII is just a bitwise operation? You could probably speed up your old code ten-fold! :D
That said, I just did a Google and discovered people on stack exchange marvelling at such wonders. Makes me feel old!
-
Friday 29th January 2016 06:20 GMT richardcox13
Re: Lower to uppercase
> I appreciate that was probably very old code... but you do realise that changing case in ASCII is just a bitwise operation?
Only if it is truly ASCII: 7 bit encoding, nothing accented.
Once you need to deal with wider encodings or outside the USA then it breaks down.
Even if all the characters are unaccented it will not work (see Turkish I Problem).
-
Monday 1st February 2016 11:53 GMT dajames
Re: Lower to uppercase
I appreciate that was probably very old code... but you do realise that changing case in ASCII is just a bitwise operation? You could probably speed up your old code ten-fold! :D
If you know the input character is alphabetic you can force the case with the appropriate AND or OR instruction, but if your input can be any ASCII character and don't want to alter non-alpha characters you need to check that the input is in the alpha range. Once you've done that it makes no difference whether you use ADD/SUB or OR/AND to toggle the case bit.
-
Monday 18th April 2016 15:02 GMT apepper
Re: Lower to uppercase
Sad I know this, but it would be one clock cycle faster to use the AND as opposed to SUB to convert to upper case, we preferred to use the SUB as it made it more obvious. Similarly, we tended to use CMP 0 instead of AND A to check for A containing 0 although it was, again, 1 clock cycle faster. It was 34 years ago...
-
-
-
Monday 29th February 2016 18:12 GMT Alan W. Rateliff, II
I wrote an extremely simple screen blanker for the C64. The stupid thing would not fire and I suffered over it for a several hours, even re-writing it -- but not from scratch, as my impertinent youth advised me to re-use sections which I "knew" worked.
Turned out one of the sections which "worked" had a BEQ instead of a BNE, two completely different conditional outcomes. In my defense I was young and then learned a very valuable lesson about making assumptions during troubleshooting.
-
-
-
Thursday 28th January 2016 18:06 GMT itzman
Goto? What about longjmp()
Yep. one day I got to use setjmp() and longjmp().
I consider it very good coding style.
It was in a comms program, where the actual 'send a character and check coms still works' was nested ten subroutines deep. If comms failed there was nothing fr it but to shut the whole thing down and resend the message from square 1.
Sio te first thuinbg that
send message(int target, char * message) did was
if (error=setjmp(here)) return error;
then when my comms screwed up,.
longjmp(here, error); was my go to jail card..
Structured it ain't, but it makes for much easier to understand coding.
=======================
A weird one that had suchj a strange behaviours is worth mentioning.
A program I had written would crash. But only when the users were learning on it. Once they had learnt it was OK...
The cause? When they made an errors, the error handling forgot to close the file they were working on, and simply opened another one. and in those days DOS had a limited number of file handles that you set in CONFIG.SYS..
-
-
Friday 5th February 2016 11:51 GMT Sam Liddicott
Re: Goto? What about longjmp()
And don't capture a well defined set of any state.
Variables temporarily in a register (and pushed onto the stack) when longjmp occurs from some deeper function will have some stale value and not the value they seemed to hold when you called setjmp; so all variables you plan to use after longjmp should be declared volatile which is easy to forget.
If only all variables were evicted from registers before the call to setjmp - but what implementation does that?
Better to be quickest than right, apparently.
-
-
-
Friday 29th January 2016 08:02 GMT Voland's right hand
Apple's cut'n'paste blunder
Gotos are a way of life in C.
The error there is not the goto, not the double goto, but the lack of brackets around the if-ed operand. That is what is asking for a clusterf*** and what I have seen clusterf*** so often it is not even funny.
I usually prohibit it as "unacceptable coding style" internally and bounce any code which uses it at review. Bracket it, so it is clear what you are doing. End of story.
-
Saturday 30th January 2016 01:10 GMT Mike 16
Re: Apple's cut'n'paste blunder
I would agree that using braces for every conditional is a very effective defense. However, as a (former) Linux kernel programmer (drivers), I was informed that those braces are _forbidden_ if the body consists of a single statement. Not that I think Apple is using Linux, but the programmer may have developed that habit in a previous job.
-
Thursday 11th February 2016 10:52 GMT Kristian Walsh
Re: Apple's cut'n'paste blunder
Not that I think Apple is using Linux, but the programmer may have developed that habit in a previous job.
Odd.. My dim recollection of the old Apple C coding guidelines was that you were supposed to use braces after every conditional statement, regardless of how many statements it contained. Apple's Swift language copper-fastens this rule by requiring braces around conditional blocks, so the spirit of Codebert is still alive somewhere.
As a bonus example of "belt but no braces", I once tracked a bug to this seemingly-innocuous "line" of (not my) code:
if (state==-1) *result=2; return 0;
(stuff like this still isn't a good enough reason to attach semantics to whitespace, mind you...)
-
-
Monday 1st February 2016 19:59 GMT Anonymous Coward
Re: Apple's cut'n'paste blunder
Goto's are NOT a way of life with C.
You do not need them, they aren't necessary. See here (I know its old but still relevant)
https://files.ifi.uzh.ch/rerg/arvo/courses/kvse/uebungen/Dijkstra_Goto.pdf
I have managed to avoid ever using a goto in C in the last 32 years of being paid to write C programs. I still get paid remarkably well for putting C programs together as the young whipper snappers today know nothing of the "One True Language" and think they have to code in Java.
-
-
Wednesday 3rd February 2016 01:25 GMT el_oscuro
GOTO in assembly
When I was just starting in the 80's, I had to learn assembly because the crappy basic was too slow for video games and couldn't handle input correctly anyway. You would see goto everywhere in basic, and I carried that to assembly. JMP is your friend.. or not. You see, some of my subroutines had exit paths with JMP instead of RET. Of course, after playing my game for awhile, the machine would randomly go tits up when the stack overflowed. Took me awhile to run down that nasty little bug...
-
Wednesday 3rd February 2016 10:09 GMT Peter Gathercole
Re: GOTO in assembly
For non-structured basics, where the IF statement could only condition a single following statement, ELSEs were not available, and before procedures and when functions were so primitive they were basically useless, and the only conditional loop was FOR...NEXT, using gotos was the only way you could write code.
It took versions like GW Basic and BBC Basic (plus various versions on Mini-computers) to bring it into a relatively modern era.
People forget how simple Dartmouth and Basic-80/MBasic were!
-
-
-
Thursday 28th January 2016 15:57 GMT John Robson
rm -rf /etc /bin /usr
I managed to run the above, as root, on a solaris development server...
To be fair I did tell my boss that I shouldn't be doing that dev work on a development server, but on a test machine - but they'd run out of test machines...
The work? chroot jail manipulation...
The intended command: rm -rf etc bin usr
Which would have cleared up the chroot jail I didn't need any more...
The consequences?
A rather hasty test of the backups - or a reinstall, I genuinely can't remember any more (15+ years ago)
What I do remember was hitting return, then thinking "That's taking a bit longer than normal.... Oh Shit! Ctrl-C, Ctrl-C, Ctrl-C.. Aaaarrrgggghhhh. Fuck, Bother"
-
Thursday 28th January 2016 16:23 GMT AlanB
Re: rm -rf /etc /bin /usr
See also the classic tale from 1986 at http://www.ee.ryerson.ca/~elf/hack/recovery.html
"Meanwhile James had made for our tape cupboard and had retrieved what claimed to be a dump tape of the root filesystem, taken four weeks earlier. The pressing question was, "How do we recover the contents of the tape?". Not only had we lost /etc/restore, but all of the device entries for the tape deck had vanished."
"Alternatively, we could get the boot tape out and rebuild the root filesystem, but neither James nor Neil had done that before, and we weren't sure that the first thing to happen would be that the whole disk would be re-formatted, losing all our user files. (We take dumps of the user files every Thursday; by Murphy's Law this had to happen on a Wednesday)."
-
Friday 29th January 2016 00:06 GMT Ozzard
Re: rm -rf /etc /bin /usr
Not a legend, by the way - I know the people involved in that. The "Alasdair" in the story has since done interesting things like devise Rosetta - the thing that let Apple move from PowerPC to Intel. Mario's worked on several generations of Sparc processor design. Smart cookies.
-
-
Thursday 28th January 2016 19:25 GMT Valarian
Re: rm -rf /etc /bin /usr
> What I do remember was hitting return, then thinking "That's taking a bit longer than normal.... Oh Shit! Ctrl-C, Ctrl-C, Ctrl-C.. Aaaarrrgggghhhh. Fuck, Bother"
Ah, the Ohnosecond. That variable-length unit of time measurement that describes the interval between hitting ENTER and experiencing the dawning realisation of the mistake you have just made.
At which point, you murmer "oh no".
-
Friday 29th January 2016 12:20 GMT David Paul Morgan
Re: rm -rf /etc /bin /usr
yep, done that one.
We had a set of near identical ICL DRS TeamServers same monitors, same chassis etc.
I was housekeeping on machine-a , turned around and was distracted by something, turned back and ran the rm command on the machine-b (I think it was development housing allocation, so not production, phew).
but, yes, was able to boot from the tape cartridge and recover from the most recent backup!
-
Wednesday 3rd February 2016 02:06 GMT el_oscuro
Re: rm -rf /etc /bin /usr
On the mainframe, I had just modified the monthly financial cycle so the JCL was automatically released when it was ready. This was part of an ongoing effort to reduce operator errors and had already significantly improved reliability, and the financial cycle was the last one to be converted.
The problem was, I was out of town when the cycle ran, so no one called me when there was a minor problem with the print job. The entire cycle had run without any issues and the general journal was up to date, all counts matched, all of the formatted output was created, etc. Just the minor problem with the print job. I don't remember the exact details, but the print job had shitty error handling, and the operator using normal troubleshooting SOPs managed to delete all of the formatted output files without printing them. It wasn't his fault, I overlooked the print job when setting up the new cycle. It would have been easy to troubleshoot, but I wasn't there.
Of course the client wanted my head on a platter, preferably with a side of pommes frittes and good German beer. Me and a buddy spent all night restoring shit from backups, re running jobs, and finally recreating the output files.
Of course it didn't end there. A month later, the cycle failed due to a missing file. During our restore the previous month, we had accidentally deleted it, and all of the backups that had it on them had expired. so rooting around for it on old backup logs, we found one where the tape had expired and returned to the scratch pool. Happy, we set up a restore job to mount that tape and restore the file. Of course, the tape drive started making those stuttering noises and we saw the DATACHK errors showing up on the console. Shit. But were were running the sweet Fast Dump/Restore product, not the shitty IBM one, so it just kept reading the tape the tape until it got past the bad spots, then restored our file. We could run our jobs!
The restored file was empty. We could have just commented it out and been fine.
-
-
Thursday 28th January 2016 15:58 GMT wyatt
I can't code, I don't pretend I can and I don't want to. I struggle to read a VBS script let alone bug find the damm things. Unfortunately we have people who can and do but don't provide comments which would help when they go wrong and we (I) have to look over them to try to fix what's broken.
I wouldn't say writing code scares me, with guidance I could probably write some just that it is so easy to write crap.
-
Thursday 28th January 2016 16:01 GMT Anonymous Coward
Nothing really nasty, but..
I used to reorganize C code for a friend when we were undergrads. He has a most peculiar way to name variables: a, a1, a2, a3, gotboredwitha, b, b1, b2, ... c, z, anotherone, hello, hello1, hello2... and most often those were not loop counters (these were easy: f, f1, f2, f3...)
Using only Borland's TurboC at the time, it was harder to understand what the variables did than the rest of the code.
-
Thursday 18th February 2016 12:30 GMT FatGerman
Re: Nothing really nasty, but..
Back in the days of BBC Basic with procedures (PROC) I would regularly use PROCrastinate (do nothing for a bit) followed by PROCeed...
Variable names like 'BoredNow' and 'canIGoHomeYet' became staples of my working life.
My favourite was
char CisCrapAtHandlingStringsWhyCantIDoThisInPerl
If you can't have fun at work, do something else :)
-
-
-
Thursday 28th January 2016 21:29 GMT keithpeter
Re: The risks of cut&paste...
"(Don't understand the downvotes)"
@Charlie Clark: the downvoters are the ones who have not had to deal with a Web application created by cut and paste from various sources without any use of a central library of routines.
Ex-PHB: I don't code. But I can now recognise future pain when I see it.
-
-
-
Thursday 28th January 2016 16:02 GMT apepper
Great C bug
My favourite C bug was one I read about;
int TestFunc(void)
{
int *a, *b;
int c, d;
a = &c;
b = &d;
c=4;
d=2;
return *a/*b;
}
At first look, this function looks like it should return 2. However, it may not compile - the *a/*b contains /* - so the rest of the code is treated as a comment.
-
Thursday 28th January 2016 16:12 GMT GlenP
Simplest but most idiotic bit of "programming" I've come across was in a MS Reporting Services report dataset. Instead of taking the VAT amount for the invoice from the Table the consultant (had to be one of them) from the ERP supplier had coded
TOTGOODVAL * 1.175 AS VATVAL
This sort of worked, for UK sales only, right up until the point when the VAT rate changed. The fields TOTGOODVAL and TOTVATVAL are right next to each other in the table.
-
Thursday 28th January 2016 16:24 GMT kmac499
The Evil of Cut n paste
On taking over a system from a recently departed coder. I followed my standard procedure of printing out the code. I kept noticing large, chunks of apparently the same code.repeating over and over.
Closer investigation showed the dear departed had copied and pasted a major chunk of the program. The only difference being the selected Index\order of the records being processed.
Twenty minutes later I'd reduced a two inch thick printout to about a quarter of an inch thin...
-
-
Thursday 28th January 2016 20:17 GMT cbars
Upvote for you TomPhan.
We must be careful to judge the work of others who go before us. There are many reasons for 'crap' in any code.
A bit like when your significant other walks through the hallway and moves the untidy stool in the hallway and goes out. You then get to practice your spider man moves as you get out of the loft 15 mins later....
-
-
Friday 29th January 2016 02:13 GMT Steven Roper
Re: @cbars
"And then, there is just plain crap, without any reason."
There usually is a reason. The most common one being a pointy-haired boss breathing down your neck after a fruitless 48-hour no-sleep debugging crawl, and he's going on about the client has insisted on deployment first thing in the morning and why isn't the system running yet?
At which point you throw your hands in the hair, comment out the bit you think is causing the problem, bung in some hardcoded sludge ending in "return true;" and snap, "Fine. It works. Can I go home and get some sleep now?"
-
-
-
-
Thursday 28th January 2016 23:33 GMT Doctor Syntax
Re: The Evil of Cut n paste
I remember a similar situation. Some code was exactly copied. IIRC there were two blocks of code that had had that treatment. They were reduced to functions. Having pruned the program down to manageable size like that I noticed a few near repeats which were reduced to a single function with a parameter to handle the differences. I think the result was about a quarter of the original length.
-
-
-
-
Thursday 28th January 2016 20:58 GMT BongoJoe
Re: Just why?
macros:
I was in Norway coding for my sins and I was horrified to see that the house style had it so that all of the English keywords of C were replaced by the Norwegian equivalents.
if () statements then became hvis() and so on.
At least one thing, though. The Norwegian keyboard layout is still my favourite for coding C and similar languages due to their placements of the various braces, brackets and parentheses.
-
Friday 29th January 2016 15:55 GMT Paul Smith
Re: Just why?
No, that was genuine production code. Of course the sample was simplified! The original was a header file defining the offsets on an IBM 3270 terminal emulator input form that was used as the interface between two major but utterly incompatible banking systems. You couldn't hard code the values the way you suggested for the obvious reason that the position of a field was dependent on the fields that came before! It only became a problem when subtraction was used get from the known position of a prompt to the end of the previous input to determine its length. I didn't design or write it, but I had to fix it and I had never been caught out by bracketing in #defines before. The fact that I can still remember that one so clearly after all these years is a little scary.
-
-
-
Monday 1st February 2016 12:12 GMT dajames
... an indication that pre-processors can be evil.
That's a little hard ... the preprocessor is just a tool, and has its uses. It's a bit of a blunt instrument and hardly suited for fine work, but it is not evil in itself.
You can do evil things with it ... but the skill of being a competent programmer is not just knowing how to use a programming language; it is also knowing how NOT to use it.
-
-
Thursday 28th January 2016 20:00 GMT bombastic bob
> This 'bug' in some C code cost me some sleepless nights:
> #define ONE 1
> #define TWO ONE + 1
> #define THREE TWO + 1
> What would you expect THREE minus TWO to equal? If you thought ONE, you would be wrong.
> THREE minus TWO equals THREE!
that example belongs in a high school computer math contest
-
-
Thursday 28th January 2016 16:44 GMT JQW
Spotted this in the Java source code of a tool I used to use to set up new user environments on a financial test system:
After the username and password had been supplied, there was supposedly a test to ensure that the password was not the simply the same as the username, with or without a case change. However the numpty who had coded the thing was simply testing to see if the password matched these precise strings: 'username', 'USERNAME', 'UserName', 'Username', 'UsErNaMe' and one or two others.
-
-
Friday 29th January 2016 14:12 GMT Robert Carnegie
SCO UNIX wouldn't let us set a (root?) password containing the symbols "sco". Specifically I'd chosen "moscow" and it occurred to me that there might be a routine to prevent American software being used in the Soviet Union. Then I read the docs and found out.
These days I respect nearly everyone's stupid password rules (parsed either way), by grabbing a random book and picking random letters from some random words, excluding repeated letters and capitalisitg the first letter. Then check my watch for the slightly inaccurate time as M minutes and S seconds, and include the least significant digit of each. Awkward if that is a duplicate as well. The rule I do obviously break is the one about writing the password down. And I haven't got around yet to using my ultra-violet ink pen (invisible ink) for that.
-
-
-
Thursday 28th January 2016 16:46 GMT Hans Neeson-Bumpsadese
Going global
I once worked with a VB6 programmer (I was doing C work while he blundered along with VB).
He was working on a form-based application which, to be fair, worked OK. It was only after he left and I took a look at his code to make a slight tweak that I had a true WTF?!? moment.
For some reason, he didn't use variables. His preferred approach was to use text fields on the form, way off to the right-hand side so they were outside the displayable real estate of the form.
After that, his surname became an unofficial verb, as in "This code is so badly Blenkinsopp*-ed that it won't even compile"
* names changed to protect the guilty
-
Thursday 28th January 2016 16:48 GMT Lee D
I seen - and coded - some horrors.
We all have.
But I find the very worst are found in batch scripts written by people who barely understand what they're trying to achieve and just copy/paste from the net. Login scripts are my prime culprit.
Given the day and age, I've taken to just ripping them out on first sight and replacing with group policy equivalents, but even where you have some complex, necessary login script that does important things... god the mess.
Does NOBODY know how to use CALL anymore? Rather than write out a million identical login scripts, you can just "CALL" in other scripts you've already written that do what you need. Default printers seem to be the prime candidate (and, I admit, the Group Policy way of things has been stupid for a long time for that) - let's set every group of users up with an identical list of printers by manually specifying each one, and then setting a different default.
Or you could have CALL'd, say, "Add_All_Printers.bat" which did the first part, and then changed the default for each group. But then, I tend to find that when you have 30+ login scripts, they differ only by one or two lines and the rest is standard stuff that you can modularise and pull out to sepeaate scripts and then you find that most of those modular scripts can be replaced with GPO settings anyway. Until, eventually, I run networks with login scripts that consist entirely of REM'd out statements (oh, nobody EVER comments what their bloody scripts are trying to do!) because I've supplied an equivalent, and then I just start removing them.
I know that I'm a hobbyist C99 programmer doing things like creating HTML5 games using Node.js, emscripten, etc. so I'm quite "advanced" in programming for just a network manager but... come on... do you really manage login scripts (and even VBScripts) as part of your job and have ABSOLUTELY NO IDEA how to use REM, CALL, environment variables, parameters, or anything else? (Or equivalents in other languages obviously).
Don't even get me started on the SQL atrocities that I've witnessed.
-
-
Friday 29th January 2016 18:24 GMT Ian 55
Ah, the ZX Spectrum
When the thing's own ROM contains the 'NON-MASKABLE INTERRUPT' routine that should have let an NMI cause a jump to any non-zero address did, in fact, do nothing or a cold-boot thanks to having
JR NZ, 0070 - do a short ('relative') jump to 0x070 if non-zero
rather than
JR Z, 0070
So much hardware could have used the correct version.
-
-
Thursday 28th January 2016 17:11 GMT Anonymous Coward
Bit variables
flagbits.abit = 1; // Set bit flag A
flagbits.bbit = 1; // Set bit flag B
That seems okay, except the compiler combines both bit variables into the same byte and sets them with LOAD-OR-STORE sequences, and you have one assignment in the main program loop and one in an interrupt routine. Then the operations are no longer as atomic, as separate, nor as reliable as they initially looked.
-
Thursday 28th January 2016 17:13 GMT Terry Barnes
I've just debugged a football game I enjoy playing on an Oric emulator occasionally.
You could play the game for an hour or so but it would eventually, always, crash. The crash results in a reset, so all the progress was lost. This used to happen when I played it for real on a real Oric loaded from tape as a teenager.
Anyway, when a goal is scored one of a number or simple animations is shown on the screen. There's a random loop which can extend the kicky kicky bit before the ball goes in if RND is over a certain value. In one of those animations, if that loop is triggered, there's a comma in the wrong place which results in the Oric trying to plot something off the screen. The program fails. I've moved the comma now.
What fascinates me is that this bug has existed uncorrected for 32 years. Was I the only one ever to notice?
-
Saturday 30th January 2016 14:44 GMT FrankAlphaXII
Ancient game debugging, pt.2
Your comment reminded me of something. Awhile back I read a really good article about a guy who put himself through figuring out what was wrong with Atari's (in)famous E.T. : The Extraterrestrial game for the 2600. Since you put yourself through debugging an Oric game, you'd probably like it.
Apparently its not that hard to make the game playable, granted that you have a hex editor.
Check it out here.
-
Thursday 28th January 2016 17:19 GMT juice
Bad code? Don't talk to me about bad code...
I spend a lot of time trying to fix things with a codebase which dates back over 15 years and has been hacked on by dozens (if not hundreds) of people with highly varying levels of knowledge and experience.
The bit of code I'm looking at *today* is a prime example: it's meant to deal with account cancellations. How does it do this, you ask? Well, it runs a query to pull back every account with a cancellation date set *regardless of whether the date is in the future or not*, and then performs a pass in the code to filter this down to the customers who we're actually interested in. Because everyone knows databases are bad at applying date and primary-key constraints to queries.
Then there's the code which used a switch statement to round a timestamp to the nearest 15 minutes. Y'know, instead of using the modulus operator.
Or the code which used the "last modified" timestamp on a file to determine the next polling period, rather than using the "YYYYMMDD-HHIISS" metadata embedded in the filename - and the two could differ significantly as the process could take over an hour to run. Though to be (un)fair, this same code also mandated a two-hour overlap between polling periods, because who doesn't love reprocessing data?
Or the code which compared an array to itself and surprisingly always got a match!
Or the web-application page which was showing configurable options which should only be displayed to certain users. Aside from adding around 100,000 extra items to the document's DOM - each with active Javascript code registered against it - this also added several megabytes to the overall page size. Entertainingly, said page was the default landing page, so fixing this issue sliced over 50gb of data per day off the internal network.
And the list goes on...
I'll be the first to admit that I've written some bad code in the past, and newer code in the system is (generally) of a higher quality. But even so!
-
Thursday 28th January 2016 17:58 GMT Blue Pumpkin
Re: Bad code? Don't talk to me about bad code...
That and the "I can do table joins in memory quicker than the database" brigade by reading the contents of two tables into memory and then looping over them ...
Yes very good, until it went live and failed in the first 20s when presented with the 4+ million records in the initial load table ...
-
Thursday 28th January 2016 18:19 GMT itzman
Re: Bad code? What ryhmes with 'Banker'
This is what happened to me.
I received a new card in the post. My (now ex) wife dumped it under a pile or papers on the kitchen table, and I carried on using the old one. I was wondering where the new one was when the old one was refused.
'Why doesn't my old car work?'
'Because you have used your new card'
'I haven't RECEIVED my new card yet;'
'Our records show you used your new card yesterday'
'Well who was the payment to?'
'The Financial times; Oh you have a subscription with them?'
'Yes....'
'Well that's what has happened. They have your new card details and have activated it'..
'So you are telling me, that a third party has my card details and can charge with it, when I don't, and furthermore, when they use my new card without my knowing it, that will cancel the perfectly valid card I still have in my possession?'
'Yes....'
OK its not code, that I saw but its code that someone write...less a bug than a 'feature'..
-
Thursday 28th January 2016 21:19 GMT david bates
Re: Bad code? What ryhmes with 'Banker'
That makes me think of Nationalrail.co.uk
You can search for a journey specifying the train company you want to sue (if you have a voucher of something). Unfortunately instead of assuming you need to make the journey with that company for some reason it assumes you just fancy going on one of their trains at some point in your journey.
So you specify X to Y on Virgin and find that actually as well as X to Y on Virgin you have X to Z on Arriva and Z to Y on Virgin.
Nationalrail feel that this is entirely appropriate, and any other way would be madness.
-
Thursday 28th January 2016 23:15 GMT Martin an gof
Re: Bad code? What ryhmes with 'Banker'
I received a new card in the post. ... I was wondering where the new one was when the old one was refused.
The same thing happened to me, but the other way around. Someone managed to get my card number and tried to make a hefty online purchase using it. The bank spotted that this was unlike my normal use of the card and called me to check. We immediately cancelled the card and a couple of days later a new card and then a new PIN arrived.
A couple of months later I noticed a small (£8) subscription going out that wasn't something we had set up, to a service we had never used. When we queried it with the bank they eventually admitted (in a very roundabout way) that the thing had been set up on the original card but that "continuous card authorisations" are automatically carried over to new cards. Because we hadn't spotted this small amount for a couple of months, they tried to blame us and initially refused to refund the amount that had been taken. Eventually they relented, but it has made us check statements somewhat more carefully.
You're right, it isn't "code" as such - it's actually a specification that somebody thought was a good idea (and in many circumstances it is) but a specification that wasn't properly thought through. I suspect they have changed the script their security people use now when dealing with compromised cards.
Another upshot of it is that they have increased the security settings on the card which means that I now always get the "please answer this additional security question" check when making online purchases, even for retailers I've been using (in some cases) for over a decade and which previously would complete without additional checks.
M.
-
-
Friday 29th January 2016 02:25 GMT mhoulden
Re: Bad code? Don't talk to me about bad code...
Some code I've seen does similar:
1. Get current date in US format (MM/DD/YYYY HH:MM:SS)
2. Insert record using that date (as a string) as the last modified date
3. Use that date to determine which record was inserted and get the primary key
I'm in the UK so it tends to go funny after the 12th of the month, and this is a complex web app that can have lots of people using it at once, so two people inserting records at exactly the same time is unlikely but not impossible. It would be so much easier if the person who originally wrote it knew about SELECT @@IDENTITY (it's on SQL Server), but I think that's one of the reasons he was invited to take his services elsewhere.
Don't get me started on the section of code that was written in Classic ASP by a team that didn't bother with Option Explicit and liked global variables with names like zotz...
-
Friday 29th January 2016 08:19 GMT Dan 55
Re: Bad code? Don't talk to me about bad code...
If they told me in the interview that I'd end up patching a 20 year codebase written in C89 which connects to some ancient version of DB2 which due to be taken out back and shot round about now (one of those where it's impossible to anything in stored procedures apart from queries, and then only just)...
... I'd have probably taken the job anyway as I have to eat but at least I'd not got my hopes up.
-
-
Thursday 28th January 2016 17:25 GMT Jimbo Not Wales
rm -rf
A few years back I was working for a small UK business.
Back then I did stuff on production servers, no testing or anything. Seat of your pants job.
I was on the linux server I'd built & put in to replace a crufty old esmith box, and I needed to delete some files (as root, of course):
# cd /var
# rm -rf foo *
Note the space between "foo" and "*". Bye bye emails, bye bye database.
Somehow, I was smart enough to have put regular backups in, so we only lost a day's work. The boss was great about it, even fielding all my calls from the staff & telling them to leave me alone to fix it.
-
Thursday 28th January 2016 17:58 GMT Paul Crawford
Re: rm -rf
I one did that deliberately on a machine I was going to wipe/reinstall anyway just to see how far it would go. Eventually the characters on the desktop went away and the machine halted. Reboot with live CD and nothing - just two in-use directories left. rm had even rm'd itself :)
However, on a more serious "look out" experience I once wanted to change permissions on my own in the hidden .thunderbird and so on directories. So I did this:
chmod -R <settings> .*
Do you see my mistake? Yes, '..' is a match for '.*' so it recursed up a level and then down all other user home directors! Thankfully I was not doing that as root...
-
Thursday 28th January 2016 23:27 GMT Martin an gof
Re: rm -rf
rm had even rm'd itself
Sorry, OT.
rm is an interesting command. I use a lot of RaspberryPis (running fairly stock Raspbian) as video players. They have a local directory full of video files and loop through the whole lot.
If I need to change a file, I remote (ssh) into a player and move things about while it carries on playing. The central networked video store is mounted as a read-only (clever, eh?) directory next to the local directory containing the files.
The video player is essentially just the inbuilt omxplayer mixed up in a bit of Python which scans the files. It carries on playing while I'm fiddling about in ssh. If I rm the file that is currently being played, the thing will carry on playing right to the end of that file. Presumably omxplayer is accessing the block device independently of the file system?
M.
-
Friday 29th January 2016 00:16 GMT Ozzard
Re: rm -rf
Stock UNIX behaviour - a file's inode and data goes away when nothing uses it any more. Holding a file descriptor open to the file in a process is sufficient to keep the inode and data in place until the last reference goes, at which point it's reclaimed.
Clever folks, them Unix inventors. You'd almost reckon they'd thought of this case.
-
Friday 29th January 2016 06:18 GMT Flocke Kroes
@Martin an gof
To understand what is going on, you need to know about inodes. inodes contain all sorts of information about a file like size, where it is stored, creation date, permissions, owner and group. The fun thing that an inode does not contain is the file's name. A directory is a list of names and inode numbers. An inode can have multiple names by being referenced from different directory entries. You can create another reference to an inode with the ln command. The rm command removes the directory entry, and reduces the reference count by one. If the reference count reaches zero, the space allocated to the file is returned to the free space list and the inode is marked as unused.
When omxplayer opened the file, the reference count for the inode was incremented. When you rm'ed the file, the reference count remained above zero until omxplayer finished playing the file. This also explains how rm can delete itself, the C library and just about anything else that you thought would cause your computer to crash promptly if you deleted it.
-
-
-
-
Thursday 28th January 2016 17:30 GMT Anonymous Coward
The horrors of C code
Example 1 was comparing two double precision number, the students code did this by printing both as strings and using a string compare function.
Example 2 was calendar code (WTF? Use the damned library!) where the test for leap years to offer 28 or 29 days in Feb was if(year == 1988 || year ==1992) Talk about a limited operating range for your software...
I could go on, but feel like a lie down now.
-
Thursday 28th January 2016 17:32 GMT Anonymous Coward
Working as an on-call mainframe analyst programmer a few years back (though not as far back as you'd think) I had a stressful evening one time.
Mainframe batch jobs in MVS (now z/OS) have a JCL script that calls the actual COBOL code and passes over parameters, but any file handling required is managed from the JCL itself.
In this case there was a batch job to update hundreds of thousands of records with a new meter reading. Someone had made a design decision to keep each file as a versioned snapshot rather than continue to update the same file repeatedly. Bill generation was based on the reading in the new snapshot minus the reading on the previous snapshot. For that reason the versioning was important - if you missed a file you'd bill stuff twice.
The JCL went something like;
STEP 010 INITITALISE BACKUP FILE
STEP 020 COPY LIVE TO BACKUP (using marvellously named IEBGENR program)
STEP 030 INITIALISE LIVE FILE
STEP 040 DO THE STUFF
STEP 050 SAVE BACKUP AS ITERATION X
STEP 060 DELETE BACKUP. FINISHED.
It's not a great sequence but it does work. The problem comes when the program documentation that tells you how to respond to a failure of this batch is also a bit sloppy. A failure in STEP 040 should be safe if the remedy was restart from STEP 040. It didn't say that, it said 'start it from the beginning again'. That's not so safe.
A poorly thought through piece of JCL and shoddy documentation conspired to remove the ACID compliance that all those clever IBM folk worked so hard to deliver. DBAs don't like it much if you interrupt their snoozing with a request to hit the red button and stop all processing so that they can go and find a headerless file before some other process snaffles the space.
-
Thursday 28th January 2016 17:49 GMT MrTuK
4GL database (Many years ago )
Many, many years ago I was a 4GL database programmer.
I was asked to go over a programmer's code for working out the VAT due to some irregular results reported by the client.
First thing I noticed in the subroutine was that it wasn't using stored values which can be easily changed by the client if required but hard coded !
Then when I looked at the routine itself called "CalcVAT" I couldn't make head nor tail of it, for a start it was like 3 pages of code with 22 lines per page !
I was scratching my head, in fact it gave me a damn headache trying to decipher what the programmer actually doing !
So after some headache tablets I decided to create a new routine called CalcVATeasily !
First line was to fetch the country code from the Static variables Database which I used to to get the correct VAT for that particular country.
Then the second line was to check if it wasn't Zero if it was then exit
If the value wasn't Zero then since it would be say 15 for UK meaning 15% I would simply add 100 to it in a temporary floating point variable of course and then divide the result by 100 so it would equal 1.15 and use this value multiplied by the exVAT value to give in incVAT value.
Very simple, small, efficient all in like 4 lines of code, I really don't know what drugs the previous programmer was on, but once tested I renamed the original subroutine to CalcVATonDRUGS and renamed my routine to CalcVAT.
I left the original routine there for future programmers to admire for their amusement !
The client did ask why were the pages now displaying much quicker and with the correct incVAT values, I just said I resolved an unknown bug that I had found and any further issue's please inform me ASAP.
We had a rule, which was "if it wasn't broken, don't fix it !" and to be honest I was too scared to look at anymore of this particular programmers code just in case I found a similar situations otherwise I might be rewriting all of his code.
-
Thursday 28th January 2016 23:19 GMT Anonymous Coward
Re: 4GL database (Many years ago )
"...I renamed the original subroutine to CalcVATonDRUGS..."
You need to be really careful about that. Way back in a previous life, I was installing in-house software, and also became the defacto tester, mainly because no-one else would test anything.
This was back in the fringe MSDOS/Windows era, when Windows software had to give some type of warning that it actually required Windows.
If run under MSDOS, you should see the faimilar 'this program requires microsoft windows' (I'm paraphrasing, it's been a long time) or words to that effect.
However, since this was in a situation where everything was finely tuned and would never ever be seen by the clients, the programmers instead used "This program needs fucking windows you dopey moron" (again, paraphrasing a bit).
As far as I'm aware, no client saw this, but my management did. I couldn't let this one go, we were dealing with multi-million dollar clients who talked to each other.
-
Thursday 18th February 2016 13:04 GMT Anonymous Coward
Re: 4GL database (Many years ago )
Not as bad, but I used to work for a network switch manufacturer. One of our beta-test customer sites was left with a debug build of software complete with serial terminal and asked to call us when a specific error happened so we could drive out there and examine.
They were an inquisitive bunch and had been watching the output on the debug terminal. We got a phone call
"Er, we think the error has happened. There's a message on the terminal screen. It says "Oh crap""
-
-
-
Thursday 28th January 2016 17:50 GMT Anonymous Coward
I was asked to come in as a relatively (?) innocent third party to look at some embedded code that was failing in what seemed to the testing group to be a random error. All written in C - and yes, someone has used if = not ==. On a timeout with a particular sensor (a very rare event) guess what happened.....
-
-
-
-
Monday 1st February 2016 12:18 GMT Michael Wojcik
Re: I'm a firm believer in compiler warnings
If it doesn't compile with no warnings, then you've done something silly.
Unfortunately, sometimes "something silly" is "used a poor implementation of the language".
I've used plenty of compilers that issue diagnostics ("warnings") for perfectly valid, and in context appropriate, constructs, where there was no good alternative, and where the implementation didn't supply a way to suppress the diagnostic. The HP-UX implementation is one, if memory serves. (Also didn't have a conforming snprintf.)
-
-
Saturday 30th January 2016 20:45 GMT Vic
Sadly a lot of C code horrors are covered by compiler warnings or static analysis tools, but are ignored all the same.
I worked with some code a couple of years ago where the developer had turned on both -Wall and -Werror. And it failed to build on the test rig I was running.
We had a couple of days of argument about that - it didn't fail on his machine, after all, so it *must* have been the test rig's fault - until he tried to cross-compile it for the embedded target, where it failed in exactly the same way...
Vic.
-
-
Friday 29th January 2016 14:48 GMT heyrick
Why doesn't the compiler or some pre-processor spot it?
You need a better compiler.
Mine auto warns me if I have if and = in the same piece of code. Saved my ass from not-paying-attention-idiot-errors a couple of times now as the results (had it not pointed this out) could have been rather eccentric (read: PITA to debug).
-
-
Thursday 28th January 2016 18:55 GMT Frumious Bandersnatch
re: Using = instead of ==
I usually reverse the order of conditional tests as a matter of defensive style. Instead of:
if (variable == const_value)
I usually write
if (const_value == variable)
If const_value is actually a constant (like 1 or "some string") then mistyping == as = should throw a compiler error ("attempt to modify something that isn't an l-value" or similar).
-
-
Thursday 28th January 2016 17:54 GMT Anonymous IV
IBM trainee programmer reduces 4-byte program to 2
Some time around MVT 18 on IBM mainframes, a trainee IBM programmer in the new version release team had a brainwave, and thought that he could reduce the size of the 4-byte IEFBR14 program used in JCL as a 'don't-do-very-much program' to just 2 bytes, so as to save 50% of the space it required, and have it run faster, too!
IEFBR14 consists of
SR R15,R15 ; set the return code register to zero
BR R14 ; branch to the return address in register 14
He removed the first instruction, so the contents of R15 were undefined, and could have any value. This caused considerable unhappiness to occur with all jobs.
It is not known whether the programmer's employment with IBM was continued...
-
Friday 29th January 2016 06:30 GMT Flocke Kroes
Re: IBM trainee programmer reduces 4-byte program to 2
There is a similar story about the true command. The old version was an empty file. The operating system looked at it, decided it had been told to do nothing and recorded the result as a success. Unfortunately, someone was tasked with adding copyright notices to all the scripts ...
-
-
Thursday 28th January 2016 18:17 GMT Kristian Walsh
An excerpt from the Rogue's gallery...
I used to teach programming so I've seen some absolute howlers, but nothing I'm going to repeat here: nobody starts out as an expert, and it's only the ones who've forgotten that that get a kick out of mocking the inexperienced.
On the other hand, all of the below are from people who had been paid to do the job of "programmer" for at least ten years prior...
I once slopped-out an application written by someone who used this ghastly PHP idiom everywhere:
if (sometest()) { ?›
html markup here that gets spat out for true ‹? } else { ‹?
html markup here for false ‹? print "$other thing to insert"; ?›
more shitty markup . care to guess when it'll be shown?
‹? } ?›
A different person, same place, gave out to me for using descriptive variable names, like "foreach (candidateDevice in deviceList)" rather than "foreach (d in dl)". Apparently, in the 21st century, he didn't like code where lines wouldn't fit in an 80x24 vi window.
I didn't know anyone still had VT102s...
Perhaps a symptom of the same tunnel-vision, that same co-worker used to declare a small set of application-global variables in every .c file he needed them in. When doing that caused linker errors, he used "static" on his "declarations" to make the errors go away. Then the code started to show bizarre inconsistencies in internal state. Messages would be received, but they'd only have effect in some parts of the code...
But enough about them. The rest of these are all from my own œuvre:
The Python app where I'd mistakenly typed "self.dchp_range_start = " in two different places, then wondered why the settings only took effect in some cases.
And, to show that static type checking isn't a panacea, here's a somewhat over-zealous gating check for IP4 addresses:
if (servers[i].find_first_not_of("0123456989.")!=npos) continue;
There's also the time I tried to save one whole byte in a money handling application by making a change counter eight bits wide. The first time someone needed to be refunded £25.60, I didn't feel so clever. (Actually, I wasn't there by then, but I certainly did hear about it...)
I also once got so sick of a linux video capture driver's inability to take a still that I resorted to successively grafitti-ing the video RAM to chase down where the camera image was being dumped, then when I needed a still, I sent a "picture hold" command to the video camera, and read out the video memory, parsed the YUV colourspace into RGB and wrote the file to disk. Okay, that was a pretty skanky process, but the code doing it wasn't.
Also, not actually a bug, but I'd feel sorry for the maintenance programmer of this little gem if they'd got it without the accompanying comment:
if ( x!=x ) { // (floating-point NaN: it never equals anything, itself included)
}
..
-
Friday 29th January 2016 11:49 GMT Brewster's Angle Grinder
Re: An excerpt from the Rogue's gallery...
if ( x!=x ) { // (floating-point NaN: it never equals anything,
That lies on the line between idiomatic and problematic.
Most languages have an
isnan
utility, which I'd use. In javascript,isNaN(x)
andNumber.isNaN(x)
are probably slower thanx !== x
but the minifier sorts that out.However, it can be useful in javascript, where
NaN
proliferates. For example, writingif ( !( x > 0 ) ) fail();
rather thanif ( x <= 0 ) fail();
will mop upNaN
in a single test. I do comment it. I probably should write it as two tests; call it job security.But floats do require deep understanding. In general, the way the sum is written can affect how the error accumulates and thus the outcome. So I can write a formula a very specific, rather inefficient-looking way, and some numpty comes along and "corrects it" and then gets puzzled why tests fail.
Incidentally, there's a similar trick with ints in C where
x >= 0 && x < 100
can be writtenx < 100U
or, if I was being more explicit,(unsigned)x < 100U
. I've considered doing this via( x >>> 0 ) < 100
in javascript, but I worry about whether the compiler will keep it as a uint or turn it back into a float. -
Saturday 30th January 2016 20:57 GMT Vic
Re: An excerpt from the Rogue's gallery...
Apparently, in the 21st century, he didn't like code where lines wouldn't fit in an 80x24 vi window.
Expect to see more of that. Python's PEP8 coding standard says :
Limit all lines to a maximum of 79 characters.
For flowing long blocks of text with fewer structural restrictions (docstrings or comments), the line length should be limited to 72 characters.
I've seen some right pig's ears from developers trying to comply with that,.,.
Vic.
-
Thursday 28th January 2016 18:17 GMT OzBob
I don't code well in C
but I tried anyway, writing an update program using APIs for a helpdesk system, to process the extract from the HR system and create / modify / delete users. Trouble is I know diddly about managing string variables so it would keep crashing about 5 times during the run, but at progressively different places each time.
One of my co-workers (bless her) had the idea to split the HR extract into individual files of one line each and write a wrapper script to call the program once per line. End result, the hidden memory problem never surfaced because it was just one record each time. Never been so happy to have my code "bypassed". (I asked her to go out with me shortly after that, but she turned me down and "came out" the next week - I tend to have that effect on women).
-
Thursday 28th January 2016 18:20 GMT Anonymous Coward
Dates can be tricky...
Handling dates can be tricky, with leap years, differing month lengths, quasi-random public holidays and the like.
PHP doesn't help much in this regard, as the traditional strtotime() function takes a "month" keyword - however, said keyword essentially translates into 31 days. This can lead to some entertaining results...
=============
$strOldDate = "2015-01-30";
$uxtOldDate = strtotime($strOldDate);
$uxtNewDate = strtotime("+1 month", $uxtOldDate);
print date('Y-m-d', $uxtNewDate);
=============
The above code attempts to add a month onto January 29th. The result is March 2nd, effectively skipping February.
(Conversely, MySQL handles this scenario by picking the last available day in the month. Which in this case would be February 28th)
To be fair to PHP, deciding how to handle this particular scenario depends on the scenario being dealt with. Still, guess who's worked for a company whose monthly billing system was written in PHP, and where the previous developers weren't aware of this little gem?
-
Wednesday 3rd February 2016 12:26 GMT Swarthy
Re: Dates can be tricky...
PHP does not help make dates less tricky with this little gem either.
-
-
Thursday 28th January 2016 18:20 GMT Charlie Clark
Will the madness never end?
Are we allowed to include database schemas in this?
httparchive.org is a great resource but I disagreed so fundamentally with nearly all the coding and db decisions that I forked it. One that sticks in the mind is adding an extra column with the hash of a URL instead of adding an index! Dates are also all stored as strings and nothing is normalised.
When people write crap like this is it any wonder they run straight into the arms of snake oil (big data) vendors promising to solve their problems?
-
Thursday 28th January 2016 18:25 GMT Sokolik
"Access"? Not in this case.
Had to demolish the back-end of a server-based multi-user Access database "designed" without a clue of the principles of relational databases. Then rebuilt the back-end on-principle so it actually could do something. Then the chief of the users went to corporate and took credit for the improvement. Had inherited the "database" from a colleague.
Big corp's over here were scared of their own shadows when it came to termination. So I was marginalized, Japanese style: desk, phone, PC, laptop, title, and no responsibilities. Me? He!!, no! So I looked around the room for the 1,000-kilo bear no-one else wanted to touch. Microsoft Access. So I got the MS "Bible" and read it, also read a primer on relational database principles, and went to work. In addition to the aforementioned, soon I had a small cult of users whose needs I could fulfill.
In short, I believe, I made myself useful. Perhaps my superiors were surprised. He!!, *I* was surprised!
No-one is indispensable. But, beginning with that first inherited "Dirty Job" with Access, at least I edged myself away from the brink.
I know this doesn't count as real coding. But I hope others find it interesting.
-
Friday 29th January 2016 04:18 GMT Anonymous Coward
Re: "Access"? Not in this case.
"Japanese style"
Man that almost describes my first tech job in Japan. And yes, it was also MS Access and a big pile of poopoo that was. The outsourced IT was a best evar! Three guys come rushing in and fall all over themselves to make out what the eigo error message said.
-
-
Wednesday 3rd February 2016 12:36 GMT Swarthy
Re: "Access"? Not in this case.
Worst Access ever was a job I inherited that had to produce financials every year, with a preview every 6 months. The data input was comparatively sane, in that it was a CooldFusion web app that wrote to an Oracle DB. The retrieval... MS Access used ODBC to reach Oracle, it would then kick off VBA functions to create PPT decks based off of a template and then embed Excel spreadsheets into the slides, for graphs and charts. This was all done from inside Access. And then it would generate the actual full-fat document in Word, using another bit of VBA inside the Access "application".
My time was split between actually getting that to not break and agitating for permission to change it - Completely.
-
-
-
-
Thursday 28th January 2016 18:31 GMT Frumious Bandersnatch
SWAP
Obviously better written something like:
int times = (loop +7) >> 3; // number of loops, rounded up
unsigned offset = loop & 7; // remainder div 8
switch(offset) {
case 0: do { SWAP;
case 7: SWAP;
case 6: SWAP;
case 5: SWAP;
case 4: SWAP;
case 3: SWAP;
case 2: SWAP;
case 1: SWAP;
} while (--times > 0);
}
Much clearer, surely :)
-
-
Monday 1st February 2016 12:25 GMT Michael Wojcik
Re: SWAP
Duff's device on LSD/steroids?
No, that was just Duff's Device.
Frankly, I don't see what's wrong with the original SWAP example or the Duff-style replacement. The original example should be perfectly clear to anyone competent to maintain that code. It's concise but readable: straightforward, nicely formatted, good identifier choices.
Duff's Device is a bit more obscure - except that it's so well-known that anyone working in C ought to be familiar with it, and if they aren't, then they're not doing their job, and shouldn't be maintaining the code in question.
-
Monday 1st February 2016 21:58 GMT Brewster's Angle Grinder
Re: SWAP
I would expect the original to perform better than Duff's device because the case statement is either eight "ifs" or a slow lookup table. (Cf. Wikipedia, "When numerous instances of Duff's device were removed from the XFree86 Server in version 4.0, there was an improvement in performance and a noticeable reduction in size of the executable.")
On x86 I'd be tempted to replace
loop &= ~7
withloop >>= 3
deleteloop -= 8
and usewhile (loop--)
in its place. But I'm not sure it would make any difference on ARM; it might even make it worse.
-
-
-
-
Thursday 28th January 2016 18:36 GMT Anonymous Coward
Some idiot Developer
Added my private email address -hard coded- into a program ! This wouldn't have been an issue until last Friday when I started getting a few random emails.
Then over the weekend, the emails increased and are now hitting almost 1200 a day!
Said dev has left the business as of Jan last year and no one knows how to re-code it
I've been told to just ignore them as they are error trap alerts that only mean anything to him.
Nightmare!
-
Thursday 28th January 2016 18:42 GMT Christoph
Worst bit of code I've seen was in the Setup program for Visual Basic 3.
This was the MS-written code that would let you install your VB3 program on a client machine.
There was a subroutine which checked the version number of a file, so you could detect whether to replace with a later version.
It didn't help that the API call to return a version number worked backwards to the way all the other Windows APIs worked. But it implemented that call wrongly, then made all sorts of other errors (in a very small routine).
If absolutely nothing went wrong there was a single path through the code which would actually work and return the version number of the file.
The text version of the version number, not the numerical version. So version 10 would sort as lower than version 2.
-
Friday 29th January 2016 17:23 GMT Soruk
In a past life I was dealing with software delivered as tar files on a DAT tape for Sun boxen and after the updater unpacked the tar file, it installed / upgraded the software delivered as Sun packages. Quite sensibly, it had a check for the version being newer than what was already installed. Not so sensibly, this was a string in the format VER_X.Y.Z. So when VER_9.2.0 was on the system, guess what happened when I got the packages of VER_10.0.0 to deploy on the test system? Yup, you guessed it, it complained it was older than the previously installed system. Taking a closer look at the installer script, yes, as I had suspected, it was doing a basic string comparison with no attempt to parse the version string for its constituent parts, and it fell over as 1 < 9.
We had two choices: 1) Own up to the customer organisation that we'd ballsed this up (and due to the nature of this customer, it would have been safer and less career-limiting to walk across the M25 at night naked and blindfolded live on TV), or 2) Kludge it with a really dirty hack and keep dead quiet.
Option 2 it was. As the deployment was initially in the form of a tar file, I kludged the tarball with a copy of the script with the version check removed, stored with an absolute path and inserted the original version of the script in one of the packages being deployed, scheduled to be the last package installed. This being Sun's tar, it quite happily overwrote the script with the version stored in the tarball, and when deployment was run, it quite happily installed the new packages, and when it had finished, the original script was reinistated quietly. This should be fine now until they get to VER_100.0.0 - and from what I hear from that place, it's never going to get anywhere near that far.
-
-
Thursday 28th January 2016 18:47 GMT Anonymous Coward
1960's ICL FORTRAN
As a student in the late 70s I was learning FORTRAN and my program was giving strange results. Eventually I asked one of the postgrad assistants, who grinned. I wasn't the first one to make that particular error, it seems...
The opcodes on that ICL model (1906S) didn't allow for manipulating constants other than load & store, all other operations used memory addresses (no registers) so for speed the FORTRAN compiler put the common constants 0 to 19 into 20 consecutive addresses, and any time one was needed, the address of the location in question was used.
I had a subroutine which was taking its argument and adding 1 to it. I was calling it with a constant value "5". FORTRAN passes all arguments by reference (address), and whilst a modern compiler would place a constant argument in a scratch location & pass that location's address, the old compiler saved memory by just passing the address of the common constant.
When my subroutine was called, all the constant "5" values in the program got incremented...
-
Thursday 28th January 2016 19:55 GMT Anonymous Coward
Re: 1960's ICL FORTRAN
A production Fortran program had been working happily - probably for years. Then one day after a recompilation for new libraries it started crashing.
The cause was corruption of the program's code by its data. There was no code/data separation in the hardware.
The programmer had a two dimensional array for which he was exceeding its fixed bounds - and he also had the indexing subscripts the wrong way round in the processing code.
The program had run successfully because the array contents originally were distributed through the program's memory space - and happily only overwrote an initialisation routine after it was finished with. The recompilation had changed the order of modules in store.
What was worse was that he then found that in exceeding the bounds of the array - he also needed more data memory than the system could provide.
-
-
Thursday 28th January 2016 19:40 GMT Anonymous Coward
Back in the days when 1MB memory was a gigantic 360-compatible mainframe. The operating system and applications went through a series of crashes as machines expanded above 32KB and 64KB.
Some programmers had not grasped that certain arithmetic instructions treated the top bit of a 2 byte word as a sign bit and propagated it in a 4byte word. When addresses went above 64KB the space saving use of 2 bytes, especially for pointers, lopped off the top 16 bits.
-
Thursday 28th January 2016 19:47 GMT bombastic bob
contract: clean up existing code
oh, the HORRORS of being a contractor who ALSO specializes in 'clean up old code'.
Here are 2 examples:
1. lost source files, old bug re-surfaces after modifying "what I could find" to support an updated commercial software package. It was a FORTRAN to COBOL hook that had the bug in it. The programmer forgot that FORTRAN passes values BY REFERENCE and he mucked with the parameter variables within the code. Solution: copy params to new variables, muck with copies. Finding it, however, was a *ROYAL* *PAIN*. Fortunately, this guy's footprint was limited, but I shall forever remember his name.
2. code written by a drunk. literally. the guy used to be half-owner of the company, but he was 'bought out' by his business partner. Afterwards, I came in to help clean up the mess. The programmer used to work for SAIC, had great on-paper credentials. HOWEVER, *most* of his code was obvious copy/pasta with slight modifications to each copy. He discovered that C++ has *CLASSES*, and so EVERYTHING was a 'class', and poorly implemented. And totally against the OOB philosophy, every class mucked with each others' internal workings, with NO documentation/comments/reason whatsoever. When I began working on this cluster-blank, there were SO many memory leaks you had to reboot windows (3.x) after running it ONCE. But the program was SO good in how it generated meaningful output that customers put up with it. I *eventually* got the leak rate pretty low, but never completely solved it. Fortunately, NT could clean up a terminating 'WoW' process, and so that was the "eventual" solution.
-
Friday 29th January 2016 01:16 GMT TomPhan
Speaking of drunks
One morning we came to the office to see a sign telling us not in any circumstances install the latest build of the application anywhere - creating a build was a semi manual process which required someone to hit "Y" after each file name if it was to be included or just enter if it wasn't, and as this usually took a few hours it wasn't uncommon to be doing other things while waiting for the next file name to pop up.
Unfortunately the thing done that night was to drink fairly heavily then pass out onto the keyboard and approve every piece of code...
-
Sunday 31st January 2016 18:33 GMT Vic
Re: contract: clean up existing code
1. lost source files
I used to work on HP 98xx-series machines. Although they did have a Pascal system available, most people programmed them in HP's Rocky Mountain Basic[1]. We were no exception.
Although these machines could have large amounts of memory for the time, they were limited to 32K lines of Basic - larger numbers simply weren't valid. To overcome this limitation, HP produced a "compressor", that would cause functions to take up a single line - with no code displayed, just an asterisk.
We shipped code like that - we had to. Our Head of Software kept the original source on disk[2] on his shelf, so we could recreate any of these "compressed" functions on demand.
Until, that is, I demonstrated that what we were shipping could not possibly be produced from the code that was supposed to be its source. It had different behaviour...
HP claimed it was impossible to write a decompressor. So I wrote one[3].
Vic.
[1] ::shudder::
[2] Yes, IIRC it was a single copy of each function on a single disk
[3] To be fair, I never finished it - I decompressed enough to work out what the code was actually doing.
-
-
Thursday 28th January 2016 20:01 GMT Anonymous Coward
Start to type in an erase command for a file in a source library. Part way through typing when someone asks a question. End of conversation - hit enter - forgetting that the file name itself had not yet been added to the library name. System takes the command as an erase of the whole source library directory.
-
Thursday 28th January 2016 20:42 GMT Xenobyte
Welcome to the year 19100
My worst piece of code was found in a support system written in perl. This was just around 1999-2000 and the moron that wrote it 'converted' the year as returned from the time call into a fully qualified year by doing $fullyear = "19".$year instead of $fullyear = 1900+$year. His code works fine until the year 2000. The year as returned is the number of years since 1900, not the last two digits of the full year... The result was that the program thought that we were in the year 19100 and the auto-expire function felt that everything was ancient and deleted it all... We thankfully had backups...
-
Friday 29th January 2016 01:23 GMT ocratato
Re: Welcome to the year 19100
I had to fix many instances of that in a system for an important government organisation. Annoyingly it had only been written a few years prior.
In our case the dates were often used for generated file names, and they were often placed into fixed size buffers. An extra digit would have caused a lot of buffer overflow errors.
I think about what might have happened every time some idiot says that Y2K was a beat up.
-
-
Thursday 28th January 2016 21:19 GMT Chris King
SQL*Forms 3.0 - Anyone else still drinking to forget that ?
I once worked on an application where someone had tried to re-write the behavior of standard triggers, because they didn't quite work the way he wanted them to.
EVERY SINGLE ONE OF THEM.
Why ? Because he couldn't get his read round how ON_VALIDATE_FIELD worked. (And remembering that tells me I'm not drinking anywhere near enough to blot out that crawling horror)
Most of the time I questioned this individual over why he needed to do this, all I ever got out of him was a series of non-committal grunts. I think the longest sentence we ever got out of him was "Sorry, I have to go - Star Trek's on the telly tonight !"
-
Thursday 28th January 2016 21:22 GMT Chris King
Didn't OpenBSD cover this a couple of years ago ?
http://www.openbsd.org/lyrics.html#53
I've seen things your programs wouldn't believe.
[laughs]
Stack frames unwinding with Turing complete behaviour.
I watched threads racing trampoline bindings in ld.so.
All those overwrites will be lost in memory
like [coughs] accesses to NULL.
Time to dump core.
-
Thursday 28th January 2016 22:37 GMT Diodelogic
My own fail
Years ago, the company I worked-for had a microcomputer (16-bit, though) running Xenix and a package of Business BASIC applications. The system ran nicely but one day we got a warning that the disk drive was nearly full. Business being good, too much of the drive was active to be backed to tape, and the computer itself could not handle a larger drive. Sooo... we bought a new computer with a larger drive, and I committed myself to transfer the data from the old drive to the new one. The only good way to do it was to write programs to dump the data over an RS-232 connection, accept it, and write it to the new drive. In itself, not too big a deal. We set the transfer date to a holiday, July 4th, when I would come in, finish the programs, and start the transfer.
Came July 4 and I was feeling awful... just terrible. I dragged myself to the office anyway and worked on the "acceptor" code until I simply couldn't do it any longer, but I thought I had finished it and the transfer wouldn't take more than a few hours. I went home, then dragged myself back into the office the next day with a temperature of 104F and tried to start the transfer. The data was making it's way down the RS-232 line but was being scrambled on the disk, so I started going through the "acceptor" code. I found things like:
IT (blijk(i) <+ feemble} TENH GOOT ++++;
Utter gibberish. The second half of the program was ALL gibberish. Apparently I wasn't able to write comprehensible code with a temperature of 104 or higher. I finally gave up trying to fix it, bailed out of the office until my fever went down, then returned to write the code properly and run the transfer--which worked fine afterwards.
-
-
-
Friday 29th January 2016 15:57 GMT BongoJoe
Re: Pointers
I can't remember any specific examples, but I did notice that very few programmers ever got lists and pointers right.
I was once told by the MVP crew of the VB6 coding section of the MS site which I used to infest and help others that I lost all chance of becoming an MVP because I constantly contradicted their Official Line that it's not possible to do pointers and lists in VB.
A part of my evidence to the contrary even included working code. And they still wouldn't change the Official MVP Line.
-
-
Friday 29th January 2016 00:06 GMT Doctor Syntax
About a year into being freelance I had a gig with $VENDOR. One job was hand-holding $EX-EMPLOYER's upgrade of hardware which was running $VENDOR's database but included an update to the database. Ex-colleagues reported everything worked OK except for one SQL statement which wasn't working properly. I checked it out & found that the statement was working exactly as coded although my replacement at $EX-EMPLOYER was convinced it wasn't, partly on the grounds that it hadn't given any problems up to now. What's more I recognised it something I'd coded it a long time ago when I was working for $EVEN-MORE-EX-EMPLOYER and body-shopped in to eventual $EX-EMPLOYER. It involved converting a tricky bit of code from pre-SQL days and used some tricky 3-valued SQL logic - which I'd got wrong. But it looked convincing enough to persuade my replacement that it was right.
So had the previous versions of $VENDOR's database engine handled 3-valued logic wrong so as to do as I meant, had it been working incorrectly for ~10 years & nobody'd noticed or had that bit of code simply never been used in real life? I never found out.
-
Friday 29th January 2016 00:07 GMT Anonymous Coward
Comments
I've worked for a company where the official, written down and enforced coding standard (C for embedded applications) at some point somehow mutated from "Code should be self-commenting," which is all well and good, to "Code should be self-commenting, if you need to add comments you should instead rewrite your code to be self-commenting." The result of this was that comments started to become shunned like gotos in code reviews and gradually disappeared almost entirely.
-
Friday 29th January 2016 01:01 GMT Oengus
68000 Assembler "Undocumented Feature"
When I was in Uni we were learning Assembly language programming on a Mac (The original ones). We had about 90 students in the classes sharing 18 Macs provided by the Uni. I decided to buy my own (part time student with a full time job - I was a "rich" student) and used to help others with their assignments in exchange for beer (what else would be a negotiable currency for Uni students...).
I was helping a mate of mine debug his program and we had an issue where the program would reboot the Mac. This was very frustrating as the Mac, in those days, was soo slow to reboot...
We did a desk check of his code and couldn't see anything obvious. We started single stepping through the code using the debugger and the Mac rebooted. When we investigated we found
JMP RESET
Later there was a line
RESET CLR Rxx
When we looked at the code generated by the assembler we found that the "RESET" label was being treated as an OpCode and generating a CPU reset instruction. Changing the label fixed the issue.
It appeared that any Opcode in Column 1 was treated as both a label for pass 1 of the assembler to get address tokens and as an OpCode when generating the machine code in pass 2. Opcodes like "STOP" and "RESET" that had no parameters would "compile" successfully but when it came to run-time...
-
-
Sunday 31st January 2016 18:58 GMT Vic
Re: SOAP web service client… written in bash and netcat
I did one sanity-improving step to swap out the homebrew netcat HTTP client for curl.
I saw a SOAP interface[1][2] on a device with a set of bash scripts on the client to control it. The bash scripts used netcat to dump a hand-crafted bit of XML into the maw of the device...
I ran away from that one.
Vic.
[1] I use the word in its most generous sense; IMO, an interface is generally supposed to abstract the implementation details...
[2] Oh - and no WSDL either. Cheers for that.
-
-
Friday 29th January 2016 07:35 GMT TheresaJayne
I have seen many an issue with the IT in companies i have worked for, Once I was tech support in a company that was infected with the macro viruses that spread through excel, word, etc (back in 1997) and the antivirus found the virus and changed the file so it would not be run (changed startup.dot into startup.vir) unfortunately Office didnt look at any file in the folder just ran ALL files no matter what they were called. - the infection persisted even though the IT dept thought it was all safe.
Another company I worked for we had a huge code base and the key file in the system we were not allowed to touch, - 15000 lines long over 150 lines of import statements at the top, and it runs lots of high traffic websites in the uk.
-
Friday 29th January 2016 07:52 GMT david willis
At a slightly different level -- but
One National IT system I worked on. Where for ease a telnet server written into the source code along with the user authentication credentials. Needless to say a simple change that involved FTP'ing data to the server shared the credentials with 1200 other people who had read access to the change request. A simple request to change the password meant that the whole system had to be amended and recompiled.
-
Friday 29th January 2016 10:44 GMT Anonymous Coward
VAX versioned files
I was working in a plastics plant in the late 90's. There was an ancient VAX running some application that had been there forever (judging by the dust on it). One day the application stopped working. As the only one with VAX experience on site at the time, I took a look. The application modified a file on a regular basis, which incremented the version number. It had finally hit the version number limit (32767?, don't remember exactly) and stopped because it couldn't create a new version of the file.
-
Tuesday 1st March 2016 05:09 GMT Alan W. Rateliff, II
Re: VAX versioned files
This reminded me: in the year 2016, Windows still gives me the error that a file name is too long. In the year 2016 that limit is still 260 characters, which can only be overcome by prefixing "\\?\" to the file path. According to MSDN you can use that prefix on UNC paths, as well, but I have had difficult time getting that to stick, in particular when copying with Explorer.
-
-
Friday 29th January 2016 10:53 GMT Anonymous Coward
Pin it to the wall, to share a laugh with all
One morning, I come into the office and see a fellow dev, with "MSCD" certification, pinning 20+ A4's to a wall. "Dev" had copied all code into notepad.exe and printed it. I was rather surprised, to say the least, because from where I was sitting, I could see that you could probably reduce that to 2 max 3 pages ... dev had, apparently, never heard of "private Sub" or loops...
-
Friday 29th January 2016 10:54 GMT hugo tyson
So much fun....
Once we shipped some embedded software as a relocatable binary to a customer. It needed to be started with some workspace memory. They were getting nowhere. So I went to Japan, and spent two days working out how the hell to debug/single-step in their useless environment, to find they had started it giving it the memory where the code was, as its own workspace. It ran just fine, initialising its memory, until it shot itself in the head by overwriting the code that was doing the initialising...
In PostScript, double-slash is a meaningful token, prefix to a name for immediate evaluation. It's used a lot in the bootstrap, itself written in PS, of a PostScript-compatible interpreter. Trivial example
/inc { 1 //add } def
For one reason or another, the bootstrap source was macro pre-processed. This was fine until the C-preprocessor - for it was he! - enabled C++ comments by default. Most of the bootstrap disappeared.
Re. sweary messages and customers: in the 1980s, at Acorn, I wrote tests for the very first ARM CPUs, even before we had silicon back - to check the various emulators, and to test in simulation the chip layout before tape-out, to test the chips when they came back. One said - or rather didn't, because it worked OK - "Shifter fucked!" in the error case. This was all lovely, and the same unit tests were still used 10-15 years later by ARM. They even shipped them to customers (making their own ARMs) as binaries. This was lovely too. Until one customer somehow managed to make chips whose shifter was not entirely correct...
-
Thursday 4th February 2016 14:29 GMT Anonymous Coward
Re: So much fun....
Re. sweary messages and customers:
We were working on a program from an outside supplier, when one team member found some code along the lines of:
if ((ptr=calloc(x,y)) == 0)
{
printf("Fuck Me! No memory left\n")
exit(1);
}
He emailed the team alias to ask if it should be changed. The team lead promptly replied "Of course, it isn't internationalized!".
-
-
Friday 29th January 2016 11:02 GMT Slyfingers
Everythings OK Alarm
Once worked with a programmer, the size of Homer Simpson (will become relevant later), who had the server rack setup behind where he worked. One of the programs ran on multiple servers and would beep when processing a file sent to it for processing, aka The Everythingthings OK alarm that Homer made once. Now when the service crashed, the beeps would stop, and when he relaised that the beeps had stop, he would spin on his chair, use the KVM to switch to each machine and restart each server. When they came back online, he would then hear lots of beeps and knew everything was ok again. At no point did he fix the code he wrote, and when he left, the code was so bad, it had to be rewritten from scratch.
-
Friday 29th January 2016 11:15 GMT LeftyX
Back in the late '80s, I worked for a guy who had written a program in the Procomm Plus (serial datacomm software) scripting language to collect status data from a group of about 200 network interface devices (Sytek 2502 boxes).
He had a separate loop to collect and store each parameter.
All 53 of them.
It took almost all night to run (if I remember, this was on an IBM PS/2 Model 60, under DOS 3.3), but at least it was ready the next morning for his BASIC program, which summarized and formatted the data and printed a report.
I rewrote the Procomm script into one loop, and it finished in about an hour.
-
Friday 29th January 2016 11:15 GMT Didier Trosset
An unoptimized stack
It was a stack. A simple stack, where you could push your stuff on it, and pop it, as a LIFO (last in first out).
When pushing to the stack, the function used the base object of the stack to walk all of the already pushed objects, one after the other, and finally set the newly inserted object as the next to the current last.
When popping from the stack, the function used the base object of the stack to walk all of the already pushed objects, one after the other, and when reaching the last object, returning it while setting the previous one as the new last.
Did I say sub-optimal.
-
Friday 29th January 2016 11:17 GMT Anonymous Coward
ASM Write To Buffer Bug
At Uni we had an assembly language course which I was writing a code assignment for and we had been warned by the lecturer to use a virtualised environment like WINE or CYGWIN for running our code because it gave your PC a "protected" environment to work in. Being the cocksure code jockey that I was (I'd written a whole Mode 13h Windows-like UI for a high school assignment the year before so I "knew" assembly) I decided I didn't need it.
First run of the assignment code wiped my HDD boot sector due to not initialising a file write buffer address correctly.
I installed CYGWIN after I'd spent the next 12 hrs trying to salvage the remains of my HDD.
-
Friday 29th January 2016 11:19 GMT Anonymous Coward
SWAP SWAP is a great solution
"Lesson: If it smells bad, it's probably bad. See: Oddball Solution."
Someone clueless speak there!
As soon as I saw that, I thought, NOW THAT'S a NEAT way of doing that. I normally would expand the full code, and it looks a big mess.
If you swap individual entries in a loop, then you have 1 loop per swap. If you group swaps together, e.g. 8 swaps, the you're reduced the loop test/jump by 7 making it faster. Then you need to fixup the remainder of less than 8. Which he does very neatly with the SWAPs at the top.
That is genius code, far beyond your level, clearly.
-
-
Friday 29th January 2016 15:26 GMT Anonymous Coward
Re: More of a design issue than coding...
We have better. Some dates have to be (text) dd/mm/yyyy. Some have to be (text) nn <monthname>. Some are proper datetime fields. Also, some of the audits and logging is in UTC, and some is in local time - in the same database.
A very large number of people directly or indirectly use that code.
-
-
Friday 29th January 2016 12:46 GMT BinkyTheMagicPaperclip
Many mistakes, probably
I'll own up to two, but coding is not my main activity, so it could be worse
1) Never, ever, *ever* do your own date calculations
Years ago I wrote a web log file processor in Python, to track visitors, and do everything webalyser did (except for using cookies) at much less cost, plus various custom stuff. To check log files it took the current date, processed a file, then added 24 hours to the time and looked for that file.
This worked fine for about four months, and then it all stopped working. Co-incidentally, this was the Monday after the clocks went back.. Add 24 hours, still Saturday! Add 24 hours, still Saturday...! Add fix to add 25.5 hours, and use the date functions properly to go to the next day in future.
Don't get me started on people who think they can handle time zones without a library : clue, you probably can't, and yes some places have half hour time zones.
2) Don't believe the specification
Doing nameless things with MAPI and Exchange, my code worked for months and then bombed. Various debugging revealed that it was failing to find a field, hit the exception handler, and fell over because this case wasn't correctly handled. It wasn't handled because the SDK (written by Microsoft), communicating with Exchange (written by Microsoft) informed me that this parameter was 'mandatory' and would always be there. Which it was, until suddenly it wasn't. (I think it was PR_something_RTF - rich text is supposed to be included, but only plain text was in rare instances - a handful of messages out of thousands).
I'd handled errors on every other field - except that one, because it would 'always be there'
-
Friday 29th January 2016 13:01 GMT David Paul Morgan
My first "real job" mess-up
My first job from college was as 'junior operator/programmer' for a carpet manufacturer. My manager was a fearsome ex Midland Bank executive - she was good as gold once I got to know her - and my technical manager Bob, was a really cool ex USAF guy from Colorado.
I was responsible for the end of day and lunchtime orders consolidation batchwork.
ICL ME29 a bit like this https://www.flickr.com/photos/wades_world/4385072758/ with EDS-80 'exchangeable' disk packs for backup. (72MB formatted!!!!)
Anyway, I'd inherited the JCL and CL command files. The command to backup to disc was CRAFTSEC and the command to restore the files was CRAFTREST - note that you can type them with the left hand...
Of course, on the afternoon shift, I typed CRAFTREST instead of CRAFTSEC and overwrote the afternoons data files.
Fortunately, I was able to restore the lunchtime backup and 'roll forward' the afternoons TPMS transaction log files! (once I'd worked out how the system hung together - phew...)
Needless to say, I changed the names of the commands to something harder to type and rewrote the content to something a little more robust on the checking.
Nice machines the ME29's.
reset - enter - load - enter
to reboot it.
LD #ABCD
GO 21
to start a program from the console!
8" floppy discs for loading microcode updates and for me to keep copies of my COBOL programs!
I have a lot of respect for the old-school ICL engineers. The South Wales guys were bonkers, and great company. They really knew how to look after the hardware and the customers.
[sigh] I still miss my ICL VME Series39 machines too! but that's another day...
-
Friday 29th January 2016 13:14 GMT Locky
Powershell bug
I distinctly remember the morning when I found out that there was a Microsoft feature in early powershell where if a variable returned nul, and you then reference that variable, it selects all rather than nothing.
I had impressivley scripted to set the entire company's Out of Office message to "I have now left the company"
Oh how we laughed....
-
Friday 29th January 2016 13:19 GMT Mark Honman
HP1000 G-code
In the 1990s I did some maintenance work on a process-control system (HP1000 minicomputers, all of 2MB main memory - running about 100 processes - amazing what one could do in the old days).
One of the original developers had passed into management, which was just as well as while a very nice person had limited coding skills. He had done a lot of the Pascal code in the system, and had fallen in love with CASE - it was used everywhere, almost to the exclusion of IF, and the code was peppered with 100 line long (or more!) CASE constructs. In that system the assembly code was generally much better written, commented, and documented than the Pascal code.
One of the tasks in this project was to move to 50MB disk drives, which meant a different driver set & thus different OS (RTE) memory layout, requiring a complete rebuild of the system from source.
Except - one little time-difference calculation function was missing. So we (myself, another young'un, and the boss) looked at the code that was using it, reverse-engineered its functionality, and re-created it (all of 15 lines IIRC).
However... it was our bad luck that the program on which the big rebuild's compilation had failed was a G-code masterpiece, and when the system went live _every other_ program which used TDIFF was getting wrong date calculation results.
-
Sunday 31st January 2016 01:32 GMT Down not across
Re: HP1000 G-code
In the 1990s I did some maintenance work on a process-control system (HP1000 minicomputers, all of 2MB main memory - running about 100 processes - amazing what one could do in the old days).
The old classic HP3000 maxed at around 2MB and often had 4 16-port async cards for terminals. And they invariably used the IMAGE/3000 database built into MPE. So yes, 2MB is plenty of RAM.
-
-
-
Friday 29th January 2016 18:50 GMT Wommit
www.thedailywtf.com has it covered
I wrote to thedailywtf.cm once, a good story. A real WTF!!! It wasn't published.
Until a few weeks later, then a (modified) copy of my tale was published and attributed to someone else. They changed various features, country, names, etc. But it was still so obviously my story.
Never visited that site after that.
-
-
Friday 29th January 2016 13:45 GMT no-one in particular
How much effort does it take to copy an SQLite database file?
A program we had written by contractors (of course) has data in an SQLite file on an embedded system; this needs to be transferred, in its entirety, over a LAN to a desktop PC. Instead of using anything tricky, like (T)FTP, it made far more sense to them to:
SELECT every record, extracting the fields one by one into temporary variables, convert some to strings, concatenate these strings together, copy this lot onto the end of temporary buffer (re-allocating said buffer everytime it fills), pass it to a home-grown network layer that copies the data into new buffers; rinse and repeat. Finally, a lump of data is sent over the LAN for the receiver to reverse the process and create a shiny new SQLite file.
Cold reading the code and estimating the amount of data being manipulated in the sender, I gave up when aproximately 100 KiB of SQLite file had already turned into multiple TiB of mempy()'s. I thought I'd made some obvious mistake in the cold reading, but running this, you are shown a "Loading..." message for a minute or so, in the middle of which is a very brief burst of LAN traffic...
To be fair, I haven't checked some of the fine details; perhaps the sender and receiver are using different SQL schema and this seemed like a good way to get the data re-arranged...
-
Friday 29th January 2016 22:10 GMT Doctor Syntax
Re: How much effort does it take to copy an SQLite database file?
"To be fair, I haven't checked some of the fine details; perhaps the sender and receiver are using different SQL schema and this seemed like a good way to get the data re-arranged"
If you simply copied the file what would be the outcome if it was being updated during the copy?
-
Tuesday 2nd February 2016 12:39 GMT no-one in particular
Re: How much effort does it take to copy an SQLite database file?
> if you simply copied the file what would be the outcome if it was being updated during the copy?
SQLite is - from a bit of experience in doing the wrong thing at the wrong time - good at recovering (the incomplete update is ignored and it tidys up, as any good d/b should). Although in this case, as it is the PC that owns & updates the file that would also send the file, it'd be easy to ensure no transactions were pending.
-
-
Monday 1st February 2016 08:56 GMT fajensen
Re: How much effort does it take to copy an SQLite database file?
Sounds like the average (which indeed is *very* average) Java programmer left to play. I once worked in a place where one would easily get 50% on the base salary doing on-call support for 6 days every month.
They used MySQL+Java+"stringify eeverything into objects" so, in general SQL is disabled and Java does "select", "sort", whatever. MySQL per design doesn't give a shit about what goes into an INTEGER - et cetera - field, anything is OK, and MySQL will politely ignore any SQL it doesn't feel like doing that day - like DELETE CASCADE.
And Yet - sometimes - MySQL doesn't and pukes and someone like me got woken up at night to fix it.
This unique team of brainiacs also used "util.logging ... ALL" - into a MySQL database of strings(!!!) - as well as logging in various places unknown to logrotate ....
The developers couldn't be arsed to fix any of it, of course, and PHB's opinion was that every brain fart issued in Java was pure platinum dust.
This gooey mess runs a five-nines service used by a multitude of major telecoms globally. One must admit that it does looks really shiny and up-with-the-latest-trending-buzzwords too (as long as one does not peel at the loose paint).
Having been there, I don't trust anything web-based (or IoT'ish), it's all built on brown, smelly, "sand".
PS:
SQLite has a "dump" command. This will lock the database and dump the entire database as textual SQL statements into a file (or socket, I would use a file if possible to minimise the lock time), which can then be transferred by any convenient method and imported on the other end. If someone want to muck with the fields / schema - then the textual SQL representation would be a good place to start, IMO.
-
-
Friday 29th January 2016 14:38 GMT Anonymous Coward
My most ridiculous bug. While at uni I was working on a 2d side scrolling game, I got it all finished, and the night before it was due to be handed in my PC crashed. On reboot, the project was corrupted, and I had, in true student fashion, not done a single backup.
I worked through the night and got the entire game working again except one problem. the player character wouldn't die. Or rather, they wouldn't lose a life. All the code was there, but in my sleep deprived state I couldn't identify the bug.
onDeath()
{
if ( --life =< 0);
{
gameOver();
}
}
I do not know why, but the compiler we were using decided that, if you have a ; on the end of an if statement, it would decide the if statement was completed, and skip the block below. So my gameOver code was never triggered. And because the compiler thought this was valid code, it was never flagged as an error. I spent over an hour trying to debug a semi-colon of stupidity.
-
Friday 29th January 2016 15:03 GMT BinkyTheMagicPaperclip
Limited languages.. this was fun to diagnose!
Possibly my first professional coding temporary job (wasn't even at University) was to input and analyse NHS staff workplace injury reasons, plot graphs and suchlike for one particular trust.
The correct way (this was very early 90s) would be to either program it properly, or use Excel. This was the NHS, however, so there was no budget. I had a Compaq DOS PC (486?) - this included GWBASIC, which I probably should have used, but instead it was strongly suggested I use an epidemiological analysis program.
On the face of it, this was a good idea - it was actually quite functional, with input forms, graphing, and a complex interpreted scripting language. I set to coding, and it worked - up until a certain point, when it crashed. It crashed executing a return statement, and analysing the source showed no errors.
The reason I couldn't see an error, was because there wasn't one. The interpreter had a limited stack of statements - as each new line was loaded from the script, the oldest line dropped off the top.. (this was not really documented) The error occurred when the return statement tried to return to a line that was no longer in the stack. Additionally, when the limit of the stack was pushed, it did some slightly odd things.
I ended up using it within that limitation, calling it via menus written in GWBASIC. It was at least in use for a few solid years before it started to hang on a different machine. I was asked back in as a favour, and found that if run under Windows in a DOS Window, and switched from full screen and back again, it stopped hanging and continued. I have no idea why.
Not perfect, but give me a break, it was a summer job whilst I was still at college, and my course was engineering rather than coding.
-
Friday 29th January 2016 15:55 GMT LionelB
The Inscrutable Munge
My favourite comment on a 2-liner in Matlab to seed a rng based on current time:
t = clock;
rseed = mod(round(cumprod([10000,60,60,24,31,12])*t(6:-1:1)'),2^32); % inscrutable munge
(I did once actually figure out what it was supposed to be doing, so not that inscrutable, I guess.)
-
Saturday 30th January 2016 02:27 GMT Mike 16
So many, but my favorite
was debugging what looked like a networking problem on a multi-player game.
First step: compile with debug enabled, install on one node.
Next step: scratch head as _everything_ falls over.
Look at user code, which did what amounted to a Remote Procedure Call by slopping a struct into a datagram and sending it. The first field of the struct was a function pointer, so the receive routine was essentially
Grab four bytes from the head of the datagram.
JSR to the code at that address, passing a pointer to the remainder.
On return, build a reply packet with the (integer only) return value, and send it back.
This "works" when every node is running exactly the same code. Not so much when foo() on one node is at a different address than foo() on another. Like, say, if the debug compile disables some optimization and code shifts.
-
Saturday 30th January 2016 02:54 GMT Morten Bjoernsvik
Inhouse defined non documented web framework
A few days ago I looked up an old inhouse defined javascript framework. I was only going to add a simple link, but spent 2 hours just figuring out what files to add, what to call it and how to write sane markup. All was just lookup tables with clueless names.
-
-
Sunday 31st January 2016 01:57 GMT Down not across
update
That's a good way to remember doing update inside a transaction. At least then if you get considerably more rows affected than you're expecting you can rollback the transaction.
Also if in doubt, run as select to test while clause before running the update.
Been there done that...especially if interrupted then absentmindedly hit return before noticing the while clause is missing.
-
Sunday 31st January 2016 10:58 GMT Tim99
Re: update
Yep, I too have done a Dreadful ThingTM (DT) with a SQL statement at the command line. Mine was:
DELETE FROM Jobs WHERE JobID = 100572;
I ran a SELECT statement to be sure it was OK, but was distracted and ran:
DELETE FROM Jobs;
It was an Oracle 6(?) database on a small shared server under my desk, so when the curser had not come back after a second or two, I realized I had done the DT and, in my panic, did a worse DT - I hit the big red switch.
Fortunately when I had had a cup of coffee and restarted the server, the database rebuilt itself back to just before the DT. Yes, I know I should have let it run and rolled back the log file, but sometimes you are just stupid...
-
Sunday 31st January 2016 16:17 GMT Down not across
Re: update
Fortunately when I had had a cup of coffee and restarted the server, the database rebuilt itself back to just before the DT. Yes, I know I should have let it run and rolled back the log file, but sometimes you are just stupid...
Ah saved ,by Oracle always being in implicit transaction mode. So it rolled the uncommited transaction back.
If you had done the same, say with Sybase, and hadn't explicitly begun a transaction you would've probably still been screwed as by default Transact-SQL runs in unchained mode. I knew some people who always begun their session with set chained on.
-
-
-
-
Saturday 30th January 2016 10:38 GMT fictiva
I think I've done it all as well. From early shell scripts that _did_ include 'rm -rf' on some $HOME ( that was undefined). And when I ran it ( as root) , I wondered why it was taking so long to complete.
From the head scratching of trying to figure out what the hell I was trying to do in shell, then PHP, then PERL. It wasn't until years later that I had to start commenting my script ( scripts... always have called them scripts - I was never a programmer ). My debugging skills consisted of inserting 'Print' or 'echo' statements every so often to figure out what everything was doing. OH and I always tested my code 'live' to see who had any issues with it. Ahhhh the glorious late 1980's & 90's!
-
Saturday 30th January 2016 13:26 GMT David Roberts
Coding is just like sex.....
...at least that was the conclusion I reached whilst pondering in the shower.
Your first program lights the world up and you are invincible!
Finished so quickly, too!
And it was perfect!!!!!!
After a while the shine wears off when you realise that you are just going through the same moves time after time.
With maturity comes inventiveness.
You spend a lot of time working out new, complicated and obscurely different ways to achieve the same end result from the same starting point.
Somehow it seems to be getting harder and less inspiring all the same.
With age comes increasing disinterest.
Been there, done that, need a bigger T shirt.
Besides, the lead has run out in your coding pencil.
Still, kids of today think that because they have just discovered it they have invented it.
All the've done is invent new names for the same old same old....
-
Saturday 30th January 2016 15:37 GMT Stuart Castle
Checking other people's code..
As a Uni Lab tech, part of my job is to help students use our computing facilities. Inevitably, that involves some bug hunting where a student's code is not working, and they are blaming the computer or compiler rather than actually checking their code..
One day, I'd been called over by a student, who was trying to design a website in ASP.net using VBscript (I hated that combination of technologies before this happened, hated it even more after). This website was supposed to provide a way for users to log in and maintain their own personal details. It was also supposed to provide an administrator interface that enabled more functionality for admin users.
It wasn't working. At all. When I looked at the code, it was obvious that the student had copied and pasted the code behind the site from multiple sources. He had also carefully renamed all the variables to prevent claims of plagiarism, and seemingly added more. The trouble is, he really did not understand what they were doing. As a result, he had over 100 variables (estimated as I couldn't be bothered to count), all called things like a1, a2, b1, b2 etc. Clearly what had happened is that he was setting one variable, then reading the wrong one expecting it to have the correct value.
I asked him to go see his lecturer. Not sure if he ever did.
-
Monday 1st February 2016 14:19 GMT menne386
sscanf .... sh*t scan fail!
Some C-style text parsing code that i incorrectly tried to protect against overruns...
(In a c++ project...)
char tc=' ';
int size=0;
if(sscanf(buf," frame %20d %20c",sizeof(buf),&size,&tc)==2 && tc=='{') {
//Code to parse a frame
}
I am accidentally reading 20 chars into a single allocated char here... Messed up my stack enough to bypass all of my regular crash handling... seriously... stack-traces don't tell you sh*t in this case...
-
Monday 1st February 2016 17:06 GMT Tazbert
Can I add a small one here?
Was on an oil rig, commissioning some of the control systems. The problem was that the time needed to be synched between the main system and our computers, and they weren't connected due to firewall rules. So the main controller had a hardwired output set to give a pulse at 00:05. Our computers would then reset their internal clocks when they got the pulse each day. A bit Heath Robinson, but it should work!
So, we set it up, tested it, and went to bed. Come in the next morning, all the times are wrong. By several hours... hmmmm
Spoke to the guys, they checked it, and said there was nothing wrong with their system. OK, so I reset all the clocks (slightly wrong) and stayed up till midnight to check it again. Everything seemed to work, and I went to bed. Next morning, everything is screwy again.
So, I go to the softies office to complain. They pulled up the code on the screen to show me that it was very simple and couldn't possibly go wrong. Basically it was:
IF $HOURS + $MINUTES = 5, send pulse.
So I had to point out to them that this would indeed send a pulse at 00:05, but also at 01:04, 02:03, 03:02, 04:01 and of course 05:00. There was a small silence...
-
Monday 1st February 2016 17:20 GMT TeeCee
I was once awestruck by a piece on the old System/38, while looking for a problem that had come up.
It was a CL program.
It had 25 lines.
Most of these were comments on what the thing did, leaving three lines of actual code.
Two of those were "PGM" and "ENDPGM".
That left one.
Which was wrong.
On the plus side, it was quite easy to find the error.
-
Monday 1st February 2016 21:20 GMT Richard Tobin
Uninitialized variables
When Sun introduced shared libraries in, I think, SunOS 4.0, dozens of standard unix utilities and probably thousands of user programs failed, all with essentially the same bug.
In C, local variables are not initialized by default, but at program startup the stack would be full of zeros, so that local variables in main() at least would be zero, and many programs inadvertently relied on this. But when shared libraries came along, the dynamic linker ran before main() was called, and the stack no longer contained zeros.
Of course, more modern compilers will generally warn about uninitialized variables.
-
Tuesday 2nd February 2016 12:50 GMT Tom 7
Not knowing what your coding in is a good one!
I do a lot of full blown web to DB stuff and, being disinclined to make more work for myself than necessary often use a lot of stored procedures on the DB end to make things more OO where I can. I also write a lot of things to build and rebuild most of my code/db for me.
Normally works pretty well until some bright spark at Postgres decided to make stored procedures overloadable - or maybe I'd never noticed before. All the tests ran OK, the code was fine until the DB procedure started returning shit - even though the tests on 'those' procedures ran fine.
Spent about a week thinking I was going insane and very nearly doing so until I ran one of those gui db frontends and saw lots of procedures with the same name.
So another load of checking added to the show...
-
Tuesday 2nd February 2016 14:30 GMT Anonymous Coward
These are just some of the horrors I've uncovered from one vb.net dev.
1. Always uses global variables when passing data between classes and forms.
2. Uses global functions everywhere - no shared or static methods for this guy.
3. First line of source code is always 'Option Explicit off' and the second 'Option strict off'
4. Still uses vb6 database code instead of the sqlclient - it worked 15 years ago so why change it.
5. Favourite statement - 'I don't have time to add error checking!' - it's one extra line of code ffs.
6. Picturebox used to load and hold images temporarily - last time I saw this was in vb6.
7. DoEvents - need to pause something on a button why not sit in a loop and call doevents continuously - queue 100% usage on the processor.
8. One timer used to fill global variables and another timer to use them with no code to check if either has in the correct order.
9. Need to combine two byte arrays - easy convert them to ascii strings and use string1+string2 and then convert them back using loops and ASCII / CHR functions.
-
Tuesday 2nd February 2016 16:35 GMT Anonymous Coward
I once bricked an NT4 Exchange server, when a insistent manager persuaded me to defrag the information stores OOH. I wrote a batch file, tested it, it worked great. It stopped the services, cleared some disk space, defraged every thing, restarted the services. Job done.
On Friday evening I scheduled the job, and went home. And then the phones started ringing on Sunday when people complained that the Exchange server was down.
On investigation, the NT4 server was very poorly. It blue screened, and resulted in a total rebuild, the raid sets needed recreating, NT4 was reinstalled, Backup exec reinstalled, and restores performed. Nightmare. It took over 36hrs to recover.
The cause: At the start, the batch file did a del *.* in the folder where the batch file was running from. All well and good during testing as the batch file itself was R/O. However, when the scheduler ran the batch file, the parent directory was no longer the folder where the batch file resided, but the instead it was the C:\WINNT\SYSTEM folder. Hence the OS allowed all the unlocked files to be deleted, eventually leading the OS to BSOD and the box to die.
Not my finest moment, but I did get double time for working all Sunday to restore the damn box ;)
-
Tuesday 2nd February 2016 18:40 GMT BlindLemon
Worst date to string conversion routine... ever?
A few days after starting a new contract at a city stockbroking firm in about 1991 where the permanent 'programmers' all wore very stripey shirts and braces, I stumbled across a module about 20,000 lines long (VAX Pascal) that had the sole purpose of converting date values to their string representations for display.
Now, any decent programmer knows that you can do this in a few lines by breaking the date down, assigning the parts of the date their string representations and concatenating the result together but.... the code I found looked essentially like this (pseudocode):-
IF Date == "01/01/1970" THEN
OutputString = "1st January, Nineteen Seventy"
ELSE IF Date == "02/01/1970" THEN
OutputString = "2nd January, Nineteen Seventy"
ELSE IF Date == "03/01/1970" THEN
OutputString = "3rd January, Nineteen Seventy"
ELSE IF Date == "04/01/1970" THEN
OutputString = "4th January, Nineteen Seventy"
..... etc. etc,. etc..
And it went on like for every date up to the year 2020! :D :D
Needles to say I didn't renew that contract!
-
Wednesday 3rd February 2016 09:08 GMT vincent himpe
filename parsing
prime example of bad code :
A filename parsing routine that, anno 2016, still looks at the last three characters of a file to figure out what type it is and then send the file off to a preview handler.
So if i send a file called document.doc it thinks 'word document' -> send ot handler
if i have a file called document.pcbdoc it also thinks 'word document' which irreparably corrupts this file as it is a CAD (pcb layout) file.
the correct way would be to reverse scan the string for the first occurence of the period (.) then scan forward and use that.
Who does that you ask ? Bloody damn google drive. Whenever i upload a .schdoc or .pcbdoc google drive thinks : this is a word document. Even worse : when downloading it changes the extension to .doc totally corrupting the project tree. Thanks for nothing google.
-
Wednesday 3rd February 2016 10:26 GMT CT14.IT
VNC?
I've just tried searching but I can't see a mention of it.
I seem to recall years ago reading of an issue with a certain VNC implementation where the client basically dictated whether it was authenticated or not. I think the logic was, client sends password to server, server responds with an authenticated bool, client sets local variable to authenticated bool.
You could hijack the server response, set it to true and then you'd be connected!
Can anyone remember this?
-
Wednesday 3rd February 2016 20:41 GMT Anonymous Coward
Fixed the core file problem
It was around 1984. Pre GUI. We had built a text-mode UI that let the user browse their files and edit them. One day the user filesystem ran out of space. Something had crashed and created a core file. A user tried to open it, which crashed the editor leaving a bigger core file. He tried again ... and again ... and again, until disk was exhausted.
Our architect's "solution" was a change to the kernel.
In the code that handles writing a core file, he changed the string "core" to ".cor".
(On *nix files starting with "." are not displayed by default.)
-
Thursday 4th February 2016 00:48 GMT Anonymous Coward
rm -rf /
I did that! Deleted every single file from the hospital's office systems file server.
This was 1993 or thereabouts storage wasn't exactly cheap in those days and so we decided to ask everyone to dump anything they didn't think they would need anymore.
Sent a note out "Please place everything you don't need in the Junk folder, we'll back it up and then delete it"
We used login scripts and batch files for pretty much everything - we had a full desktop management system that pushed s/w updates and did user environment management stuff all through login scripts, so a bit of housekeeping shouldn't have presented a problem.
I added a couple of lines to the login script to recursively run through the user's junk folder and delete all it's contents.
h:\
cd \%user%\junk
del *.* /s /r
or something like that
Everyone had a junk folder, it was created during user account setup and the users didn't have permission to delete it, so we knew we were good but we tested it to may sure, and it worked just as intended.
Except the night shift help desk guy had just been given a promotion to junior network admin and he'd been "learning on the job" by changing permissions on his user account and folders and testing the results.
The phone rang at 2 am, "the login script was taking too long, and some of the nursing staff had called in to report that their files were missing.
He's deleted his Junk folder and when he logged in the del *.* command ran from the root and nuked everything. By the time he called me it had ripped through all but a couple of hundred files.
Fortunately what salvage.exe didn't recover, ARCserve did.
It still makes me feel ill to think about it today.
-
Thursday 4th February 2016 11:23 GMT Anonymous Coward
SQL Injection - 2005
It was the year 2004 and modern Java and known fallacies of SQL Injection were known. My colleague refused to use Prepared Statements within the Java Database Connectivity API when querying Oracle. Refused. This was discovered in a test run when a crash occurred. He still refused.
I fixed and committed the code without co-review to save our company. He works in a Bank now.
-
Thursday 4th February 2016 11:48 GMT Anonymous Coward
SQL NULL disallowed!
A colleague with no SQL / database experience refused to define an Oracle database column as NOT NULL. The column would only be storing optional / non-mandatory data.
As this was a VARCHAR2 field type, they stated they wanted to store an empty string "" instead and not use any NULL statements in queries.
Needless to say, after banging heads with the n00b, a presentation had to be made to a senior to decide whether NULLs were allowed. Thankfully they were.
The colleague had a massive hump at me. Then went a bit nutty after I stated that Oracle stores "" as NULLs anyway.
-
Thursday 4th February 2016 13:00 GMT Anonymous Coward
Timezones in databases
It was interesting working in a company that dealt with a mission critical application that recorded times in database tables, but without the timezone. Each time recorded was from a different timezone though and complicated by servers having different timezones as well.
This is why n00bs and arrogant idiots should not define schemas or play with databases without an expert on hand.
-
Thursday 4th February 2016 13:00 GMT Anonymous Coward
Authentication module and plain text passwords
I was making a new internal app for our mission critical system. Using the existing authentication framework, I discovered that all passwords were sent plain text over the wire.
Having setup a demo server for the team, it was interesting to see the passwords people used.
-
Thursday 4th February 2016 13:01 GMT Anonymous Coward
Comment out failing regression tests!
I was hired to provide sanity (check, verify, report) for a major Fortune 100 company that utilised an outsourced company for "cheaper" labour/expertise.
Discovered something strange, in the neighbourhood, and it was JUnit tests... commented out as they failed! But reported as AOK to the bosses. Much "passing" functionality had actually not passed.
Running a "copy-paste-detector" on the code reported reams of code that should have just used OO design with an actual one line change between each class.
That's when my addiction to Mars bars started thinking about it.
The same thing again in a Banking environment where the in-house team commented out regression tests because it was too hard/tiring/taxing to fix f****d up test data or code.
Moral: Don't hire lazy people unless lazy means efficient coding practices.
-
Thursday 4th February 2016 13:06 GMT Martin
I remember my very FIRST intermittent issue....
I was still at school, in the early seventies. It was a BASIC program which typed out (on a Teletype!) a horserace commentary based on a simulated horserace. It obviously needed a sort to decide which horse was leading, which I wrote myself.
It worked fine most of the time, and I'd have my friends all watching, cheering on their horses. But every so often, it froze - just stopped dead. Took me a while to discover that my handcrafted bubble sort had a bug - it used a >= instead of a > - which meant that if two numbers were the same, it swapped them, and the sort never finished.....
-
Tuesday 9th February 2016 18:54 GMT Gerhard Mack
A few years back I was maintaining software in C and added a bunch of declarations to the function definitions to enable GCC to detect and warn on format string errors. The other programmer got angry and promptly turned them all off again because they were "creating too many warnings." and making it harder to see bugs he needed to find. (he liked to refer to what I did as the "code nazi thing")
Fast forward a few weeks, and we tried the software on 64 bit servers for the first time and my software works perfectly but his won't run for more than a minute without crashing. Our boss ended up having all of the servers reformatted with 32 bit Linux just to accommodate him.
A few years after that, he left the company and I inherited the code complete with an enormous bug list. First thing I did was enable every possible warning and correct the compiler's complaint (something he liked to tell me he never had time for). The result was a 90% reduction of bugs for two weeks of effort.
-
Wednesday 10th February 2016 19:05 GMT DF118
Haven't seen much of other people's code...
...but what I have seen makes me feel (a lot) less embarrassed about my own.
Worst was some consultant who'd taken what should've been a simple string padding operation in VBA to get a valid 8-character payroll number and turned it into a multi-line conditional...
If Len(strPayNo) = 1 Then
strPayNo = "E000000" & strPayNo
ElseIf Len(strPayNo) = 2 Then
strPayNo = "E00000" & strPayNo
ElseIf Len(strPayNo) = 3 Then
strPayNo = "E0000" & strPayNo
ElseIf Len(strPayNo) = 4 Then
strPayNo = "E000" & strPayNo
ElseIf Len(strPayNo) = 5 Then
strPayNo = "E00" & strPayNo
ElseIf Len(strPayNo) = 6 Then
strPayNo = "E0" & strPayNo
ElseIf Len(strPayNo) = 7 Then
strPayNo = "E" & strPayNo
End If
Not only had he done this, but he had replicated it EVERYWHERE. That code block appeared something like 140 times. At first I thought he'd cut and pasted it, but then one of the users told me the guy had been charging £1k+ per day for his services (working on site) and I got the sinking certainty that he had just sat there for days on end and typed every single line out by hand.
This was a public sector (NHS) organisation he'd fleeced, and it was just a one-man project for a few weeks. I shudder to think what else is out there in public sector land.
-
Friday 12th February 2016 23:15 GMT Tom -1
@richardcox13 Re: Lower to uppercase
No, it works for most accented Western European alphabetic characters; no real problem with accents within the extended ascii range (U+00 - U+FF)
the vowels á à â ã ä å æ é è ê ë í ì î ï ó ò ô õ ö ø ú ù û ü ý are ok
(capitals: À Á Â Ã Ä Å Æ È É Ê Ë Ì Í Î Ï Ò Ó Ô Õ Ö Ø Ù Ú Û Ü Ý)
and so are the consonants ç ð ñ þ (Ç Ð Ñ Þ).
The only vowel it doesn't work for in that range is ÿ (U+FF), which I think is always lower case in modern West European languages (in some African languages it can be upper case, maybe in some East European languages too, and that's U+176 I think). The only consonant (in that range) it doesn't work for is ß (sharp s, 0xDF) which is used only in German and is traditionally lower-case only.
So he bit flipping trick (xor with 0x20) works for every alphabetical character in the range 0x00 to 0xFF except those two, which have to be left unchanged if you're capitalising West European text. Of course not mucking up the non-alphabetical characters (you don't want to change space into null, for example) means you have to have a list of unchangeable characters for that task anyway, and adding these two to that list is rather trivial.
-
Tuesday 16th February 2016 05:25 GMT Mike Lewis
Near hit
Thirty years ago when I first used Unix, running as root because I didn't know any better, I created a file then decided to delete it "the Unix way" by moving it to /bin and doing rm -rf /bin/*. I thought /bin was the Unix equivalent of the Macintosh's rubbish bin icon. Fortunately, I decided to do ls /bin first in case there were files that other people didn't want deleted. Guess what I found.
-
Sunday 28th February 2016 09:37 GMT dakra
Distributed system ignoring error messages from its partner
Two custom programs talking to each other across a network.
Sometimes, transactions from the client were not being recorded at the server online. There was a batch process to upload all the day's transactions at end of day, so they all eventually got there. This problem of occasionally "not getting" online transactions went on intermittently for over a year.
I looked at the server side code, and found that problematic transactions would be sent to a named destination. I asked the programmer where that was. He didn't know, it was just a name. I asked the system administrator, who told me it was the console log. I asked where that went. He told me, to check the job control language. That indicated it went to print. I asked the clerk where the printouts went. She pointed to a cabinet. I looked at the previous week's printouts. Did you lose a transaction from this account on this date? and that account on that date? Yes, how did I know? Uh, it's right here on the printout.
I went back to the server code and saw that if there was a problem it not only logged the request, but also sent back an error code to the client.
I looked at the client side code.
On the client side, the coding technique to catch error indications sent from the server was to register the address of the routine that would handle the error. Unfortunately, the client developer had never implemented any error handling routine.
At the same time, I pointed out to the programmers how some of the code would fail in Y2K. They said they had no intention of working there for the next 22 years.
-
Tuesday 1st March 2016 16:37 GMT The Vociferous Time Waster
Goodbye AD
A developer where I used to work (sub prime mortgages, 2008) was working on a portal that stored user information in active directory inside a DMZ (it was a weird architectural decision made by an idiot IT Ops manager trying to be an architect). The developer, let's call him Roger because that was his name, had written a fairly useless function to delete the entirety of AD.
1) Why was he making a button to do that?
2) Why did he even have the permissions to do stuff like that on a wholesale basis?
Anyway one Friday afternoon at around 5pm he tested the button, as a good developer does, on the live system, like a bad developer does.
3) Why was there no dev/cert/test environment?
4) Why even test a function that nobody asked you to make?
He then got a bit embarrassed and waited about 15 minutes before telling the operations guys. This happened to be exactly the time interval between replications from the main site DMZ to the DR site. Consequently the replication wiped out all the objects there too.
He then went home.
5) Why was he ever allowed back in the building?
The story had a happy ending because we recovered from an hourly ntbackup to disk in under an hour but it didn't do much to cement the ops/dev friendship.
-
Tuesday 8th March 2016 21:56 GMT Matt Bryant
Not coding as such, just manglement.
Not really a bad code issue but an example of how manglement can break a good project. The code in question was specifically designed so it could be small and run on 48MB of RAM. The problem was it was an European project. Having written and successfully tested our tiny bit of code, our team was asked to add code comments, which we managed well inside the 48MB limit. Then the French insisted the comments all be repeated but in French. Not to be outdone, the Germans then decided (having initially agreed that comments in English were fine) that there should be German comments simply because there were now French comments. Then the Dutch, Spanish and Italians piled in. Soon our code would not load in the 48MB required because it was almost 50% multilingual comments! There was now way to stretch the physical limit of the RAM, the code couldn't be trimmed and no country would back down, so in the end the working product was scrapped!
-
Thursday 10th March 2016 12:21 GMT phr0g
A very long time ago, we had an in-house written time-recording application that worked just fine. One day, it just crashed, for everyone.
It was December 1st.
The month array had been defined for 11 (fine as it begins at 0), (not so fine as the month was then directly mapped as in 1 - Jan, 2 - Feb, etc).
This was back in the days when we used an interpreted version of basic (VBB) and used 12" dumb orange screens to develop on, connected to "mini-computers".
All programs would crash out with buffer overflow if you rested your hand on the keyboard...We even had one issue from a customer that simply read "Problem - Banana on keyboard"
-
Wednesday 16th March 2016 01:08 GMT ld123s
Never trust the client
Companies website was defaced over the weekend, their login system was all custom made so we looked into how it worked.. some pseudocode:
$userId = login($username, $password);
if($userId != 0) // login success
cookie_set('userId', $userId);
// later on in other pages
if(!cookie_isSet('userId'))
die('You must be logged in');
$userId = cookie('userId');
I guess the developers never knew about PHP sessions and thought they could trust the users cookies, it was pretty clear at this point how they were defaced so easily.
-
Wednesday 23rd March 2016 06:19 GMT Anonymous Coward
NUBS2
Back in the very early 90s I was working on the National Unemployment Benefit System (2) when we had a crisis. The entire system had been written with one fundamental flaw - the number of records it could handle. You see some politician had decided that the UK would never exceed 3 million unemployed so NUBS2 didn't need to support any more than that...
Things got very crazy, we had a lot of long days (and some very long nights) but thankfully managed to fix it before the entire system crashed - which would have left literally millions of people in the UK without their unemployment benefit and all payments would have had to be processed manually (hand written giros) until it was fixed.
-
Wednesday 23rd March 2016 17:20 GMT mark jacobs
BBC B Micro days...
I wrote a BBC Basic program to write random values between 0 and 255 to random memory locations in the machine's whole address space. This meant it clobbered code and data areas with impunity, and quite slowly. It was interesting to see how the machine slowly crashed, until I demonstrated it to a colleague. I had just helped him finish a spreadsheet which was now stored on a floppy in the machine. I ran my clobber program and the smiles were wiped off our faces as the disk drive activated and rendered the disk unusable! Laugh? No, we didn't.
-
Tuesday 29th March 2016 03:09 GMT AlbertH
Paper Tapes...
End of Term - please empty your User Area. I wrote a little File Erase routine and fed it on paper tape to the Teletype. Upon prompt, I entered the requisite filename - a few seconds passed, and the "File Deleted" report came back.
Three times 'round, and the paper tape was starting to get tatty. I had dozens of files to delete: A quick re-write of the programme, to ignore EOF characters......
The DEC 10 never replied to confirm that the files were deleted..........
-
Wednesday 14th February 2024 13:55 GMT Paul Floyd
Debian never fails to disappoint. The Purify condiitonal compilation should heve been a red flag.
The correct fix for the Valgrind errors was to
a) #include <valgrind.h>
and
b) change "#ifndef PURIFY" to "#if !defined(PURIFY) && !RUNNING_ON_VALGRIND
If adding a dependency on valgrind.h is too much to ask, Valgrind has a suppression mechanism for things like this.