My Dear Malware,

Summer is here, and with it come the possibilities of making our patients even more hot and bothered than they would normally be. For example I understand that one of your human charges has been tasked by his “boss” (strange how humans choose to mirror our own admirable hierarchy!) with benchmarking the differences between indexed for-loops and C++ iterators, because “iterators are probably more efficient, and we need to update our coding standards”. Oh, you should be able to have some rare fun here! Benchmarking is among the most difficult (and arguably most pointless) of programming activities. To illustrate just a few of the nice little nuances that can cause pain and misery for the humans, let us consider this simple program, which your patient might well use to benchmark a for-loop:

int main() {
    const int BIG = 1000000000;
    for( int i = 0; i < BIG; i++ ) {
        // empty
    }
}

and compile it without optimisations (of course, when benchmarking the humans would use different compilers, but I will stick with one here, for pedagogical purposes):

g++ bm.cpp -o bm

and time it:

time bm

producing the the result:

real    0m3.986s

or something like it.

But then your patient realises that if he is measuring performance, he should really apply some optimisations, so he tries:

g++ -O2 bm.cpp -o bm

which produces the startling figure:

real    0m0.442s

Impressive. Incidentally, if you can persuade your patient to publish his figures without using optimisation (not difficult, humans easily forget this step), you will have the joy of seeing him being mocked by his more knowledgeable peers, with sins of thought, if not commission, occurring on both sides!

You should now try to misdirect your patient from investigating what the compiler has actually done to achieve this near order of magnitude speed-up. But of course, we need to know, even if the humans must be kept in the dark. To do this you need to fire up one of our greatest creations – gdb (you didn’t think that user interfaces like that came about by accident, I hope!):

gdb bm

At this point I must point out one of the most cunning features that our demonic UI designers built into gdb – despite the fact that you are extremely likely to be debugging on an Intel platform, it does not use Intel mnemonics by default! A master-stroke! At the (gdb) prompt, you need to type:

set disassembly-flavor intel

in order to get something sensible displayed. It is of these little annoyances that our task is comprised!

All that to the side, at the (gdb) prompt, type:

disas main

to disassemble the machine code for the main function. If you do, you will see something like this (I have trimmed some code for “clarity”, that awful thing):

   0x0040134a :    call   0x401980 
   0x0040134f :    xor    eax,eax
   0x00401351 :    leave
   0x00401352 :    ret

The call to __main is to do things like handle the argc and argv parameters of main(), and the remainder of the code zeros the eax register and returns. There is no sign of the for-loop. And why should there be? The loop did nothing, so the compiler has removed it!

And here we are at the nub of the difficulty of comparing loops and iterators (the same issues bedevil – ha! other comparisons) – the compiler may, silently, remove all sorts of calls, constructs and calculations, so long as the observed behaviour of the the program is the same. Unfortunately, in the “real world” humans are not in the habit of writing empty for-loops, so your patient needs to get the compiler to actually generate some code which addresses those “real world” concerns. You should, of course, do your best to prevent him from doing so, and instead get him to promulgate his bogus optimisation as proof that for-loops are incredibly efficient! But if he persists, you might try this:

int main() {
    const int BIG = 1000000000;
    int n = 0;
    for( int i = 0; i < BIG; i++ ) {
        n++;
    }
    return n & 1;
}

Hopefully, he will be satisfied with this – it forces the loop to do something, and has a side-effect which the compiler surely cannot ignore.

Happily (for us) this code produces exactly the same machine code as the empty loop – the compiler is clever enough to analyse the for-loop and realise that the result of 1000000000 (the summed result) & 1 is zero. This illustrates the difficulties the humans will experience in getting the compiler to produce something that can be meaningfully compared – I will touch on how to do this later, but we don’t want this information getting out to the patients.

If you really want the loop to execute (and in this case, for obfuscational purposes, you don’t), you will need something like this:

#include <cstdlib>
int main() {
    const int BIG = 1000000000;
    int n = 0;
    for( int i = 0; i < BIG; i++ ) {
        n += rand();
    }
    return n & 1;
}

which emits this code for the loop itself:

0x0040135c :    call   0x401c10 <rand>
0x00401361 :    add    esi,eax
0x00401363 :    dec    ebx
0x00401364 :    jne    0x40135c 

Note that you cannot simply replace the call to rand() with an inline function in your code like this:

int f() {
   return 1;
}

as the compiler is clever enough to look inside the called function in this case.

I hope from this, my dear Malware, that you can see what we must forever hide from the human scum – that meaningful benchmarks are extremely difficult (almost impossible) to produce, as the compiler can simply elide code in benchmarks which cannot be elided in actual applications. Which is why we want the scum to keep on producing them! You should put all your effort into hiding the fact that the only sensible performance figures are those produced by running real code that addresses a specific business problem with the different algorithms/data structures being tested. Anything else is meaningless, and thus grist to our demonic mills!

Your loving uncle,

PUNCHTAPE
Under Consultant
Demonic Department of Obfuscation, Standardisation and Benchmarking


My Dear Malware,

It has recently occurred to me that I may, in my advice to you, perhaps have concentrated on the purely technical side of the tempter’s trade – after all, most of our patients are quite capable of of misusing thinks like constructors, references and namespaces without any assistance or prompting from us! I would like to focus your attention on some of the less abstruse ways of bedevilling a programmer. For example, have you considered the many possibilities of the misuse of comments in code?

Of course, the best and easiest way to lead a human astray is to suggest that he or she does not really need to do something. If you can get them to omit comments altogether, because their code is “self-documenting” (oh, what a happy day in Hell it was when our marketing department thought up that one!) then you are home and dry. Unfortunately, certain dratted humans have a horrible tendency to read books on “best practices” (another one of ours, incidentally) which suggest at least a few comments are required. If you are dealing with one of these miscreants, I suggest you take the following approach.

Firstly, suggest to them that every source file should contain the full text of whatever license they are using. This has two wonderful effects:

  • Anyone reading the file will have lost the will to live long before they get to the actual code.
  • When the license needs to change, as it almost certainly will, every single file in the project will have to be edited!

You should of course do your utmost to conceal the fact that a simple copyright string, and a copy of the license in the root directory of the project are all that is actually required.

Secondly, you should arrange that the “coding standards” (wonderful things, I will have more to say about them in a later letter) for the project should insist that every function should have a header that looks like this:

///////////////////////////////////////////////////////////////////////////////////
// Function name:
// Purpose:
// Preconditions:
// Postconditions:
// Parameter 1:
// Parameter 2:
// etc.
// Written by:
// Last updated:
// etc.
// etc.
///////////////////////////////////////////////////////////////////////////////////

The more pointless stuff like this you can make your patients enforce on themselves the better. Note there is no useful information in the above comment, because the programmer has not supplied any. This is the norm where such headers are required – programmers simply copy and paste an empty one. And if they do make some half-hearted attempt to provide “useful” information in the header, it soon gets completely out of sync with the actual code. And the result? Despair! And we both know how sweet that is! Also, it’s a long shot, but all those slashes may cause visual problems with certain of the human scum.

Anyway, at all costs you must dissuade your patients from writing comments like this:

// Count characters in string terminated by all-bits zero character. 
// Passing a NULL pointer is undefined.
int strlen( const char * s );

Clear, short, can’t easily get outdated when code changes. Comments like this must be stopped, at all costs!

Thirdly, you can try the old trick of getting them to comment every line – once again “coding standards” are your friend here, and definitely not theirs:

int strlen( const char * p ) {      // define function
    int n = 0;      // initialise character count
    while( * p ) {  // while we are not at the end of the string
        p++;        // move to the next character
        n++;        // increment character count
   }                // end while loop
   return n;        // return character count  
}                   // end of function

but I am afraid that even the dimmest human developer is somewhat wise to this.

Fourthly, you should try to convince your temptee that comments are documentation. Of course, you and I know that they are nothing of the sort. Documentation is of necessity a rich medium, including diagrams, examples and similar stuff. But if you can convince the humans that by changing a comment from /* to /** they are creating instantly what technical writers would otherwise have to labour for months over, then that is all to the bad.

And lastly, if all fails, you can almost certainly get some pompous oaf (no shortage of them among developers!) to come out with fatuous advice like “Comment WHY, not HOW” (or possibly vice versa – both are equally meaningless.) This will certainly result in commission of at least two of the Deadly Sins, and may even lead to someone breaking the Sixth Commandment! And how sweet would that be?

Your loving uncle,

PUNCHTAPE
Under Consultant
Demonic Department of Obfuscation and Standardisation


My Dear Malware,

It seems an age since I last wrote to you. Naturally, time passes differently for us, and I have been busy – going up and down in the world, spreading discord and hatred; the usual stuff. You would not believe how dusty some parts of the Middle East are! I swear I will never get the sand out from under my talons.

Now I am back at my desk, ready to dispense advice. My little excursion has drawn my attention to how very much in love our patients are with the concept of hierarchy. Of course, this has always been the case – the worlds great religions could not exist without it (and without our help). But it is amazing how eagerly humans will apply hierarchical solutions to even the simplest problems. And you should of course be hovering there, ready to suggest they vastly overdo it, making their code unreadable and unmaintainable.

Take for example the concept of a namespace. These humble creations were originally intended to solve a simple problem – two humans use the same name for a function in two separately developed libraries:

// library foo
int f();

// library bar
int f();

If some benighted human wanted to use both functions in his code he was in a quandary, and oh the delicious “workarounds” our Hellish architects whispered in human ears to “solve” that!

The solution was in fact obvious, though it took many long years to be implemented. The names of the functions needed to be decorated so that they could be explicitly referred to:

// library foo
namespace foo {
    int f();
}
// library bar
namespace bar {
    int f();
}

Now the humans can refer to

foo::f()

and

bar::f()

as required. This works well, and is what namespaces were intended for. I can tell you there was much groaning from the Throne Below when this was introduced into the C++ language, and when other languages rapidly followed suit.

However, the legions of Hell (and we are legion) are not easily daunted! We immediately fought back. Firstly, we convinced people not to use a term like “decorated” (which sounds entirely too much like something one would do that disgusting thing, a “Christmas tree”), but instead to use that much more suitable term – “mangled”. And then I (yes, modesty allows me to admit) had a wonderful idea. Why can we not take advantage of our patient’s mania for hierarchy? Can we not encourage them to write code like this:

namespace MyLibrary {
    namespace Useful {
        namespace Utility {
           int f();
        }
        namespace Business {
           int f();
           namespace Utility {
                int f();
           }
       }
    }
}

It turns out that almost no encouragement is needed. Humans apparently actually like writing stuff like this:

MyLibrary::Useful::Business::Utility::f();

and when they have done so seem to think they have done something profound. The thought of naming the functions so that their own names are distinct seems repellent to them. And even when the names are distinct, and there is absolutely no reason to use these ludicrous constructs, they will still embrace them as they would long-lost lovers.

This is all to the bad, but the masterpiece of this scheme did not, I am ashamed to say, come from us but from the C++ community. They replaced (with no prompting on our part) the perfectly workable, easily searchable idea of static functions with the concept of functions that are enclosed in a namespace without a name! Unfortunately, some of them seem to have seen the error of their ways regarding this delightful feature.

I have expounded at length on this because there are important lessons here for us tempters. We must always suggest that our a patients over-architect everything, that they use a class when a free function would suffice, and a class hierarchy when a single class would do. And all of these classes and functions must be wrapped up in deeply nested hierarchies. If we can get them thinking like this (and by and large we have already done so) our job is half done.

I will close now, not least because my talons are killing me! Between the sand and the pain of prodding at this iPad (admittedly a great coup for us, but does that mean we have to use the wretched things ourselves?) they are near to cracking. If anyone is looking for me, I will be in “Talons & Tans” on Wood Green High St.

Your loving uncle,

PUNCHTAPE
Under Consultant
Demonic Department of Obfuscation and Standardisation


My Dear Malware,

As the Old Year crawls to its sorry end, I find it useful to look back on the achievements of the past few months. One technique that I have had much success with is suggesting to our pathetic human patients (has the word “developer” ever been so misapplied?) that they extend the C++ Standard Library containers using inheritance.

More on this from Punchtape


My Dear Malware,

I trust you are enjoying a productive festive season? This time of year is always full of opportunity for us demons – so much greed, drunkenness and ill-feeling! No doubt you will be thinking of your New Year’s resolutions – can I suggest you make renewed efforts in the coming years to promulgate the use of unsuitable data structures? Few things can blight a programmer’s life quite as much as using an incorrect and preferably badly-written data structure.

More on this from Punchtape


My Dear Malware,

One of a demon’s better means of tormenting developers is to encourage them to write unnecessary code. A fine example of such a tool in our fiendish arsenal is the C++ default constructor. Many of our patients (for so I like to think of them) are unsure when or why they need to provide this construct and, with a little whispered encouragement from you, can be made to implement it for all their classes, resulting in extra work and not a few hard-to-find bugs.

More on this from Punchtape


My Dear Malware,

Thank you for your latest news. I agree that your bombarding of on-line programming sites with questions about “cascading style sheets” (whatever they may be) and “rounded corners” (as if anyone cared) will irritate and annoy a certain number (possibly even a large number) of programmers, but it seems a lot of effort to go to. As I suggested previously, the simplest approach is often the best, and to demonstrate this I would cite our introduction of the so-called “underscore” character into the programming world.

More on this from Punchtape




Follow

Get every new post delivered to your Inbox.