When a funny typo lead me down a rabbit hole
C is said to be a programming language that can get you anytime. There is the character arrays, uninitialised variables containing mysterious numbers and ofcourse, the dreaded pointers. Granted, it was not C itself that got me today but it happened because I was compiling C code so half the blame is on C, sue me. Anyways, this is a story about how a small typo can lead you down a giant rabbit hole and eventually become a wonderful learning experience.
The error⌗
Let’s create a super simple (not too simple) C program with pointers. This code is inspired by the super cool and funny book called Beej’s Guide to C Programming, I highly recommend reading it.
The increment
function takes a pointer p
, dereferences it, and increments it by 1. In the main
function, we have a variable i
with the value 10. We also have a pointer j
which points to i
.
Now, we increment whatever is at j
(in our case it’s 10) with the increment
function. Finally, we print a statement to see if j
has been incremented or not.
Ideally, the code should print the following statements when compiled:
But, before it can print out anything, we need to compile it. Spoiler alert: Here’s where I made a stupid typo and my computer started levitating.
To compile the C code with gcc
I ran this command.
And, instead of executing quietly it gave me this error:
What the hell is this I was just trying to code some pointers.
The typo⌗
My first instinct was to google the error itself but wait, the error stems not from gcc
but from /usr/bin/ld
. ld
is the GNU linker. From the man page:
ld combines a number of object and archive files, relocates their data and ties up symbol references. Usually the last step in compiling a program is to run ld.
Now, look at what gcc
does, from the man page:
When you invoke GCC, it normally does preprocessing, compilation, assembly and linking.
Ideally, gcc
should take care of the linking process when we run it as an ‘overall’ command. I have not specified any linker or linker related command so ld
should not be throwing an error. This is where my typo comes in.
Let’s look at the command I ran again:
What I was trying to do here was to first print all the warnings the compiler might throw indicating problems in the code. Then, I was trying to compile the pointers.c
code in the out file pointers
. The typo was right after the -Wall
flag. I had not specified that pointers
should be the out file. The actual command should be:
Here, the filename after -o
specifies the out file, in my case, pointers
. Now, it compiles and runs without errors:
But, why did the typo-ed command made ld
throw an error?
The rabbit hole⌗
To understand the error, I spent almost an hour looking through several stackoverflow questions about linking shared libraries with gcc
. This question does have some great answers but all of these require us to pass an option to gcc
. I wasn’t passing anything instead of -Wall
.
The gcc --help
does give me this:
But, then again, my option was -Wall
, not -Wl
. Why was gcc
treating the file pointers
as a shared library?
My final destination was the GNU Compiler documentation. Remember kids, always READ THE DOCS so you don’t fall in a similar rabbit hole like me. Anyways, the very first line in the GNU Compiler’s Options for Linking documentation gives me the answer.
object-file-name
A file name that does not end in a special recognized suffix is considered to name an object file or library. (Object files are distinguished from libraries by the linker according to the file contents.) If linking is done, these object files are used as input to the linker.
That’s it! Since the pointers
outfile did not end in a special recognised suffix, gcc
was treating it as an object file. However, when it tried to use this file as an input to the linker, ld
threw an error. The error is pretty self-explanatory now.
Since pointers
is an ELF file, ld
cannot use it as an input to a link.
Side note: pointers
existed already because I had compiled it earlier (without a typo). If it was a fresh compile attempt, there would have been a File Not Found error.
This rabbit hole once again taught me the importance of READING THE DOCS, which I never do and regret later. Don’t be like me, READ THE DOCS NOW okay I will stop screaming and see you in the next blog!