Horror Code: Paid By The Number Of Rows

The first thing I've thought is: "I'm missing something". But after few seconds the doubt that the author of the following code is paid for the number of lines of code come to my mind. Judge yourself:
struct data_node *node = calloc(1, sizeof(*node));
if (node) {
        node->data = NULL;
        node->info = NULL;
        node->next = NULL;
}
comm->data_list = node;
Since node isn't used anywhere else, those six lines are exactly equivalent to the following:
comm->data_list = calloc(1, sizeof(*(comm->data_list)));
The function calloc returns a pointer to a memory area that is guarantee to be blank, so there is non need to assign NULL to the members of the structure.

Checking the value returned by calloc is a good thing. It may be that there is no more memory available so that error should be handled. But in this case the author didn't take any action in case of failure.

Use a temporary variable may be useful in some situations, but this is not one of those.

In conclusion, the code is formally correct: it doesn't have bugs or cause harms and maybe the compiler can optimize it. But the point is that redundant and useless code can lead to difficulties in reading and understanding besides subtle hard-to-find bugs.

Image by goopy mart licensed under CreativeCommons by-nc-sa 2.0

How C Compilers Work Part 2 - Preprocessor

As said in the previous post, in modern compilers, preprocessing is not a separate phase but it's made together with compilation. Nevertheless, understanding the role of preprocessor is really helpful. The first thing to say is that it basically understands only rows that start with character hash (#).

In a standard program, those rows specifies header files to include and constants/macro to substitute in the rest of the file. Another frequent used feature is the conditional compilation (#if, #ifdef, etc.) to enable some part of code only if a condition is met at compile time. In this case the flag -D of GCC can be really useful.

A strange thing is the #pragma directive, used to issue commands directly to the compiler, in some cases to enable some vendor specific option. Other directives commonly used are #warning and #error; they force the compiler to present a warning or an error in special situations (usually depending on which other files are included or not included in the project).

An Example

Now let's see what a preprocessor does. Look at this simple program:
#include <stdio.h>
#include <string.h>

#define ARGS    1
#define TEST    "test_arg"

/* Main function */
int main (int argc, char **argv)
{
        if (argc != ARGS + 1) {
                fprintf(stderr, "Error! Expected %d param\n", ARGS);
                return 1;
        }

        if (strcmp(argv[1], TEST) != 0) {
                fprintf(stderr, "Error! Expected %s\n", TEST);
                return 2;
        }

        fputs("OK!\n", stdout);
        return 0;
}
Now if you compile it with:
gcc -Wall -E -o main_pp.c main.c
you'll get another C file named main_pp.c as a result (the flag -E tells GCC to only execute the preprocessor). If you don't have a compiler available, you can look at it here. Pretty big, isn't it?

What you should notice is that #include and #define directives have been processed and the comment has been removed. This obviously helps the programmer but basically almost all the work done by the preprocessor can be bypassed. In other words, the preprocessor is not indispensable. If you compile the following piece of code, you'll notice no differences in program execution compared to the original one.
typedef struct foo FILE;
FILE *stdout;
FILE *stderr;

int fprintf(FILE*, char*, ...);
int fputs(char*, FILE*);
int strcmp(const char*, const char *);

int main (int argc, char **argv)
{
        if (argc != 1 + 1) {
                fprintf(stderr, "Error! Expected %d param\n", 1);
                return 1;
        }

        if (strcmp(argv[1], "test_arg") != 0) {
                fprintf(stderr, "Error! Expected %s\n", "test_arg");
                return 2;
        }

        fputs("OK!\n", stdout);
        return 0;
}
How is this possible? How can it be that struct foo is a FILE? And what about other functions? For the answer, you'll have to wait the next two chapters of this series.

Troubleshooting

Usually preprocessor errors are easily understandable. For example:
failed.c:1:21: fatal error: missing.h
means that the header file missing.h does not exist or is not in the path. Another comprehensible error is the following:
failed.c:3:0: error: unterminated #ifdef
which remind us that an #endif is missing.

References

  • If you want to play with the above examples, source files are here.
  • A full explanation of the GCC preprocessor can be found at this page.
  • The idea for the second example has been taken from this blog post.

Reliability First - Spacecrafts

Artistic image of Rosetta, Philae and
comet 67P/Churyumov–Gerasimenko
I bet you've heard that last week, for the first time, a human artifact has landed on a comet (named 67P/Churyumov–Gerasimenko). The lander Philae and it's companion the space probe Rosetta of the ESA (European Space Agency) have done a long  and great work. At this page you can see a resume of their ten years of journey in the Solar System.

But it was not a bed of roses. The mission had some troubles, starting from the delayed launch and ended with the not so perfect landing of Philae. There have been some technical issues but Rosetta has been reliable enough to accomplish its duty.

There is a lesson that a developer can learn from this story: create your software as it should survive ten years in space without maintenance. Check every possible failure case and make it work even if the situation is not perfect.

Of course, this is a reminder to me too, since too many times I think the system would never run out of memory or disk space.

Image by European Space Agency licensed under CreativeCommons by-sa 2.0

The Day That Killed Groupon Reputation

This Thursday I was looking at the social networks in a moment of rest, when the hashtag #defendGNOME gained my attention. For the ones that are not Linux addicted, GNOME is a famous desktop environment that had several forks (XFCE, Mate, etc.) and it has been the main choice for Ubuntu for many releases.

All the messages in Twitter and Google+ (and I suppose Facebook too) linked to a communicate in the GNOME Foundation website. Below there is the relevant part of the message, followed by the request to donate.
[...] Recently Groupon announced a product with the same product name as GNOME. Groupon’s product is a tablet based point of sale “operating system for merchants to run their entire operation." The GNOME community was shocked that Groupon would use our mark for a product so closely related to the GNOME desktop and technology. It was almost inconceivable to us that Groupon, with over $2.5 billion in annual revenue, a full legal team and a huge engineering staff would not have heard of the GNOME project, found our trademark registration using a casual search, or even found our website, but we nevertheless got in touch with them and asked them to pick another name. Not only did Groupon refuse, but it has now filed even more trademark applications [...]. To use the GNOME name for a proprietary software product that is antithetical to the fundamental ideas of the GNOME community, the free software community and the GNU project is outrageous. Please help us fight this huge company as they try to trade on our goodwill and hard earned reputation. [...]
In few words, last spring Groupon decided to create a tablet with a proprietary OS and name it Gnome, in spite of that name is already being used since several years from an open source project. So the Foundation started a fundraising with an associated social network campaign.

The result has been quick and massive. I just want to show you one tweet among the others, very representative of the dimension of Groupon fail:

Probably someone at Groupon had understood what was going to happen and quickly tried to calm the things down with this is the communicate (the emphasis is in the original).
Groupon is a strong and consistent supporter of the open source community, and our developers are active contributors to a number of open source projects. We’ve been communicating with the Foundation for months to try to come to a mutually satisfactory resolution, including alternative branding options, and we’re happy to continue those conversations. Our relationship with the open source community is more important to us than a product name. And if we can’t come up with a mutually acceptable solution, we’ll be glad to look for another name.

UPDATE: After additional conversations with the open source community and the Gnome Foundation, we have decided to abandon our pending trademark applications for “Gnome.” We will choose a new name for our product going forward.
So the happy ending has come. The name GNOME is safe and it will continue to indicate only an open source software. And Groupon will remember for many years that the community is more important than lawyers and money.

Image by ilnanny licensed under CreativeCommons by-nc-nd 3.0

How C Compilers Work Part 1 - Introduction

Build button
I'm writing this series of posts because it seems to me that many young programmers lack a clear idea about what's behind the "Build" button on their IDE. In my opinion, this happens because nowadays the interpreted languages (such as JavaScript, Python or Lua) are perceived to be more fancy and cool to learn.

The truth is that many companies still use compiled languages like C and C++. This ends in several developers (some of them absolutely remarkable) that keep losing time to understand how to fix an "undefined symbol" error.

An Overview

C Compiler
Operating diagram of a C compiler
The main purpose of a C compiler is to generate a binary file starting from one or more C source files. The generated file may be an executable or a library but in every case it contains low level machine-code instructions that a processor can execute.

A C compiler (such as GCC) is made of three logical blocks: the preprocessor, the compiler properly so called and the linker. Each block performs a set of specific tasks and produces an output for the next block but for performances reasons, usually the first two are implemented together.

Just as a side note, the first C++ compilers were implemented as preprocessors for C compilers.

Other posts in this series