C Language Undefined reference errors when linking


Example

One of the most common errors in compilation happens during the linking stage. The error looks similar to this:

$ gcc undefined_reference.c 
/tmp/ccoXhwF0.o: In function `main':
undefined_reference.c:(.text+0x15): undefined reference to `foo'
collect2: error: ld returned 1 exit status
$

So let's look at the code that generated this error:

int foo(void);

int main(int argc, char **argv)
{
    int foo_val;
    foo_val = foo();
    return foo_val;
}

We see here a declaration of foo (int foo();) but no definition of it (actual function). So we provided the compiler with the function header, but there was no such function defined anywhere, so the compilation stage passes but the linker exits with an Undefined reference error.
To fix this error in our small program we would only have to add a definition for foo:

/* Declaration of foo */
int foo(void);

/* Definition of foo */
int foo(void)
{
    return 5;
}

int main(int argc, char **argv)
{
    int foo_val;
    foo_val = foo();
    return foo_val;
}

Now this code will compile. An alternative situation arises where the source for foo() is in a separate source file foo.c (and there's a header foo.h to declare foo() that is included in both foo.c and undefined_reference.c). Then the fix is to link both the object file from foo.c and undefined_reference.c, or to compile both the source files:

$ gcc -c undefined_reference.c 
$ gcc -c foo.c
$ gcc -o working_program undefined_reference.o foo.o
$

Or:

$ gcc -o working_program undefined_reference.c foo.c
$

A more complex case is where libraries are involved, like in the code:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, char **argv)
{
    double first;
    double second;
    double power;

    if (argc != 3)
    {
        fprintf(stderr, "Usage: %s <denom> <nom>\n", argv[0]);
        return EXIT_FAILURE;
    }

    /* Translate user input to numbers, extra error checking
     * should be done here. */
    first = strtod(argv[1], NULL);
    second = strtod(argv[2], NULL);

    /* Use function pow() from libm - this will cause a linkage 
     * error unless this code is compiled against libm! */
    power = pow(first, second);

    printf("%f to the power of %f = %f\n", first, second, power);

    return EXIT_SUCCESS;
}

The code is syntactically correct, declaration for pow() exists from #include <math.h>, so we try to compile and link but get an error like this:

$ gcc no_library_in_link.c -o no_library_in_link
/tmp/ccduQQqA.o: In function `main':
no_library_in_link.c:(.text+0x8b): undefined reference to `pow'
collect2: error: ld returned 1 exit status
$

This happens because the definition for pow() wasn't found during the linking stage. To fix this we have to specify we want to link against the math library called libm by specifying the -lm flag. (Note that there are platforms such as macOS where -lm is not needed, but when you get the undefined reference, the library is needed.)

So we run the compilation stage again, this time specifying the library (after the source or object files):

$ gcc no_library_in_link.c -lm -o library_in_link_cmd
$ ./library_in_link_cmd 2 4
2.000000 to the power of 4.000000 = 16.000000
$

And it works!