3

The following code is throwing undefined symbol error on Linux.

$ cat rms.c
/* sqrt example */
#include <stdio.h>
#include <math.h>

int main ()
{
  double param, result;
  param = 1024.0;
  result = sqrt (param);
  printf ("sqrt(%lf) = %lf\n", param, result );
  return 0;
}


$ gcc rms.c
/tmp/ccaWecFP.o(.text+0x24): In function `main':
: undefined reference to `sqrt'
collect2: ld returned 1 exit status

If I replace argument to sqrt() with (double)16 then program is compiling and executing. Why is this throwing error in first case.

alk
  • 69,737
  • 10
  • 105
  • 255
Chandu
  • 1,837
  • 7
  • 30
  • 51
  • 1
    For sqrt() you need to reference the math library --- add -lm to the gcc command line – jim mcnamara Apr 01 '13 at 12:18
  • possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – Colonel Thirty Two Jun 30 '15 at 14:11
  • 1
    I'm voting as "not a duplicate" because the "why *does* this work with a constant" is not answered over there. – o11c Jul 01 '15 at 01:17
  • Related: https://stackoverflow.com/questions/8780603/undefined-reference-to-sqrt – melpomene Jul 30 '19 at 14:04

5 Answers5

4

This is a linker error.

The linker is missing the implementation of sqrt(). It resides in the library libm.

Tell GCC to add it by applying the option -lm.

alk
  • 69,737
  • 10
  • 105
  • 255
3

The implementation of sqrt() is available in the math library or libm.

You have to link your program to the math library, as:

gcc rms.c -lm

A natural question is, how am I supposed to know this? The answer is in the manpages. If I do "man sqrt", I see the following. Note that the linking instruction is provided in the synopsis.

SYNOPSIS
       #include <math.h>

       double sqrt(double x);

       Link with -lm.
Arun
  • 19,750
  • 10
  • 51
  • 60
  • 1
    Then why is that the program getting compiled and linked if a literal is given to sqrt() as argument, even though Im not linking with libm ? – Chandu Apr 02 '13 at 05:05
  • It compiled successfully since `math.h` was duly included. But, based on the error message reported ("undefined reference to `sqrt' collect2: ld returned 1"), I do not think the linking succeeded. – Arun Apr 02 '13 at 17:39
  • With literal as argument to sqrt() it got compiled, linked and executed too ! – Chandu Apr 04 '13 at 05:28
2

You must link with libm

gcc rms.c -lm

If you want more explanation Linking with external libraries.

Good Luck ;)

Quentin Perez
  • 2,833
  • 20
  • 22
  • 1
    Then why is that the program getting compiled and linked if a literal is given to sqrt() as argument, even though Im not linking with libm ? – Chandu Apr 02 '13 at 05:05
2

As the other answers say, you need to pass -lm in order to link to the library containing the sqrt symbol.

The reason it works with a constant argument is because sqrt is allowed to be implemented as a builtin. When GCC sees a builtin function called with constant arguments, it can calculate the result at compile-time instead of emitting a call to the external function in the library.

o11c
  • 15,265
  • 4
  • 50
  • 75
0

The other answers here discuss the linking error; I'm going to add an answer about why the result is correct if you replace param with a constant.

GCC has an optimization where it replaces functions with builtin equivalents (such as sqrt) and constant arguments (such as 16.0) with the results of those calculations (such as 4.0).

This is a form of constant folding.

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76