back to article 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 …

Page:

  1. Brewster's Angle Grinder Silver badge

    Everything I've ever written. It's awful. Don't look at it. Any of it.

    1. Anonymous Coward
      Anonymous Coward

      Everything I've ever written. It's awful. Don't look at it. Any of it.

      Recognising that you have a problem is the first step

      1. allthecoolshortnamesweretaken

        What are the other 11 steps?

        Or is coding more like the five stages of grief?

        1. BongoJoe

          More like entering the seven levels of hell at times...

        2. tfewster
          Facepalm

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

          1. werdsmith Silver badge

            I cringe to think of my early efforts where I wrote code that wrote code.

            I mean it would create conditional machine code in an array depending on decisions, then put the array elements into RAM and execute them.

            1. TheOtherHobbes

              >create conditional machine code in an array depending on decisions, then put the array elements into RAM and execute them.

              Nowadays that's called Functional Programming.

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

            1. Brewster's Angle Grinder Silver badge
              Windows

              >(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 and STUPIDITY were both handles to the variable ST. 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.

              1. VinceH

                IIRC, Commodore BASIC as used on the Vic 20 and C64 had that first two character approach - though probably not the only version.

                1. Brewster's Angle Grinder Silver badge

                  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.

            2. David Roberts
              Windows

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

          3. Jagged

            "Don't call your variables 'a' and 'b' "

            I once worked with a guy who always called one of his variables "bob" :(

            Nice guy, though.

            1. Lee Mulcahy

              I used various girls names (Monica was a common one) until the office Monica happened to look over my shoulder one time and see her name... awkward to say the least. In my defense, I only used them in place of iteration variables instead of i, j, or k, etc.

              1. Barracoder

                do(monica)

                {

                ....

                }until(mary++)

                ?

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

    2. VinceH

      "Everything I've ever written. It's awful. Don't look at it. Any of it."

      Ditto. Which is why I'll never open source anything of mine. At all. Ever.

      In fact, I think I should add a bit to my will to say that all my source code is to be destroyed without being looked at.

      1. Brewster's Angle Grinder Silver badge

        "Which is why I'll never open source anything of mine. At all. Ever."

        That was one of my objections to open-sourcing my stuff. In reality, nobody noticed.

    3. Anonymous Coward
      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).

    4. Alister

      I've... seen things you people wouldn't believe...

      functions on fire in a copy of Orion.

      I watched C-Sharp glitter in the dark near a programmable gate.

      All those moments will be lost in time, like Ruby... on... Rails... Time for Pi.

      1. Anonymous Coward
        Anonymous Coward

        :)

        Beer for this gentleman.

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

    1. Charlie Clark Silver badge
      Coat

      I'd be tempted to say that about all PHP code…

      1. Anonymous Coward
        Anonymous Coward

        I'd be tempted to say, that shows an incredible lack of professionalism on your part, and is an example on its own.

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

    1. Phil O'Sophical Silver badge

      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.

      1. Brewster's Angle Grinder Silver badge

        Or rep movsb and friends.

        1. Anonymous Coward
          Anonymous Coward

          slow string instructions make Dillbert sad

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

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

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

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

    3. Alan W. Rateliff, II
      Paris Hilton

      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.

  4. BongoJoe
    WTF?

    I was going through one of my modules yesterday and I couldn't believe that I found a GOTO statement.

    What worries me the most was that, until then, I could have sworn that I had never written a GOTO in the last twenty years.

    Icon: just because.

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

      1. Anonymous Coward
        Anonymous Coward

        Re: Goto? What about longjmp()

        Only problem with setjmp/longjmp is they don't capture a well defined subset of the register state.

        It's implementation defined if for example the floating point registers are captured by a call to setjmp, or restored by a call to longjmp.

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

          1. gnasher729 Silver badge

            Re: Goto? What about longjmp()

            That's exactly what the C Standard says. And it also tells you that any local variable declared as "volatile" will have the last value stored. Don't complain about your tool if you don't know how to use your tool.

      2. John Brown (no body) Silver badge

        Re: Goto? What about longjmp()

        "Sio te first thuinbg that"

        I hope your coding is better than your spelling :-)

        1. Anonymous Coward
          Anonymous Coward

          Re: Goto? What about longjmp()

          Back in the day we had languages with label variables (typically containing stack frame pointer & destination address). Worked ok for handling "unexpected" error cases, but then people started using arrays of the buggers.

        2. Lyndon Hills 1

          Re: Goto? What about longjmp()

          "Sio te first thuinbg that"

          I thought it was another failed attempt at an upper casing routine.

        3. Anonymous Coward
          Anonymous Coward

          Re: Goto? What about longjmp()

          I figure his coding is flawless, but he stutters when he has to write real words. ;-)

    2. Voland's right hand Silver badge

      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.

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

        1. Kristian Walsh Silver badge

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

      2. Anonymous Coward
        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.

        1. roytrubshaw
          Coat

          Re: Apple's cut'n'paste blunder

          ... the young whipper snappers today know nothing of the "One True Language" ...

          I.e. BCPL!

          Types?? Types are for wimps!

          True programmers know what offset to add to a function so that they can skip passed the sub-routine entry code with a goto!

    3. el_oscuro
      Pint

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

      1. Peter Gathercole Silver badge

        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!

  5. John Robson Silver badge

    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"

Page:

POST COMMENT House rules

Not a member of The Register? Create a new account here.

  • Enter your comment

  • Add an icon

Anonymous cowards cannot choose their icon