The Shortest Crashing C Program

It might seem like a strange idea to want to write a small crashing C program, but in one of the courses that I’ve been teaching labs this is one of the tasks! It’s actually a very educational thing to do.

Usually students either try to dereference an invalid address, or divide by zero. Dividing by zero raises the SIGFPE signal (Floating Point Exception). Here is a small example program that crashes using divide-by-zero:

int main()
{
    return 1/0;
}

We could remove the return keyword but gcc refuses to generate code for the statement when I do this, even with optimization disabled. We can shave off a few characters from the above by transforming the statement into an assignment:

i;
int main()
{
    i=1/0;
}

Note that I have declared i without a type. This works in C89 because declarations have the implicit type int. In C99 and some other C variants this is an error. Let’s assume we’re writing C89 code, then we can even use implicit int for main:

i;
main()
{
    i=1/0;
}

That’s pretty short – 16 characters if we don’t count redundant whitespace. However, we can do better!

When a C program is compiled, the compiler creates one or more object files with symbolic references to libraries and global objects (functions and variables). The object files are then linked – symbolic references replaced by addresses – to create an executable.

The compiler provides an entry point that calls main in one of the object files. Calling main means that we try to execute the instructions at the address stored at the location main was linked to.

Interestingly, the linker has no concept of the types of different objects – it only knows of their addresses. So, if we replace main by a regular global variable, the compiler will happily build the object file because it does not care what type of object main is, and the linker will happily link it because it is only concerned with the address of main.

So, consider this C program:

int main=0;

This will compile to an executable that tries to call address 0, which is not an address that we have access to so we get the SIGSEGV signal (Segmentation Fault). Correction I was wrong about why this crashes. The program will try to execute main as if it were a function and this does not work because the compiler has placed it in the data segment, which is not executable. So it does actually not matter what the variable main is initialized to. (Thank you Zack for the correction!)

Now we’re very close to the smallest crashing C program. We can use the trick with implicit int to shorten it further.

main=0;

Also, global variables in C are initialized to zero implicitly, so this is equivalent:

main;

And there we have it, the shortest crashing C program!

Update:

Hacker News user femto pointed out that it is possible to compile and link an empty file. I did not post this because gcc will refuse to compile and link the program – it requires compiling and linking separately.

Also, if we shall be pedantic I should point out that by “global” variable I of course mean “static” variable.

15 comments on “The Shortest Crashing C Program

  1. Dividing by zero does not crash a program on all platforms. For instance, on PowerPC (under Mac OS X, if that matters) the result is just zero, nothing terrible happens.

  2. When I interviewed to work at IBM/Rational, on Purify (around 2003 or so), one of the interview questions was to write an example crashing C program. (They were looking for array out of bounds accesses, or uninitialized pointer dereferences, etc.) My answer was “int main;”

  3. If dividing by zero yields zero as a result, that’s pretty terrible, in my opinion.

  4. Actually, I thought that the PowerPC processor, when dividing by zero, returned the special float value ‘NaN’ (Not a number).

  5. Define “C”? This program is not standard C, so the fact that it compiles at all is an idiosyncracy of the compiler, not a feature of the C language. This post should accurately be titled “The Smallest Crashing Program Which Compiles in GCC”.

  6. The trick of making an int of name main (and implicitly assigning it zero) will not work on platforms without no-execute protection, for example the embedded system I’m working on would happily jump to main and try and execute the 32bit opcode 0×00000000 which you have placed there, which is a jump to self instruction in this particular ISA. This means the program would just get stuck in a busy loop not doing anything, but it’s not crashed.

    One crash I find interesting is to perform INT_MIN/-1

  7. i tried this on Intel Mac OS X, and i get an interesting “Bus error” but not a serious crash, i guess.
    given:
    int main() {
    return 1/0;
    }

    With clang (Apple LLVM version 4.2 (clang-425.0.27) (based on LLVM 3.2svn)) i get:
    $ clang crash.c; ./crash; echo $?
    crash.c:2:13: warning: division by zero is undefined [-Wdivision-by-zero]
    return 1/0;
    ^~
    1 warning generated.
    Bus error: 10
    138

    And with gcc (gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)) i get:
    $ gcc crash.c; ./crash; echo $?
    crash.c: In function ‘main’:
    crash.c:2: warning: division by zero
    Bus error: 10
    138

    Still, thanks for sharing the info about automatic assignment as ‘int’ if not declared. Interesting idea!

  8. Division by zero on an ARM Cortex processor won’t crash unless the DIV_0_TRP flag is set in the interrupt controller. If not set, a division by zero returns zero.

  9. Compiler options and runtime may vary, but how about:

    Empty foo.c and..

    % gcc foo.c -o foo -Wl,–unresolved-symbols=ignore-in-object-files

    % ./foo
    fatal process exception: page fault, fault VA = 0×0
    Segmentation fault

  10. “Dividing by zero does not crash a program on all platforms. For instance, on PowerPC (under Mac OS X, if that matters) the result is just zero, nothing terrible happens.”

    I always thought a wrong answer, esp one exceptionally wrong (isn’t 1/0 > infinity? At least that’s what I’ve been told), would be a big deal. I guess in the Mac world that’s only a problem when it’s an Intel or MS inaccuracy. :)

  11. @Don: Nothing can be grater than infinity and 1/0 is simply undefined. You can say that lim(1/x) for x going to 0 from positive side goes to infinity. And please note that lim(1/x) for x going to 0 from negative side goes to negative infinity. So you get different answers for limit depending on the side you come from.

  12. @theldoria: Also note that positive and negative infinity are no valid integers (both mathematically and in C), although they are, by definition (IEEE 754), valid floats (in C).
    Therefore, even if the result was equal to infinity (we could define it to be), it would still not work.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>