1

I have a strange problem when I try to compile the below minimal example. The first call to sqrt poses no problem, but the second one raises a linker error which I don't understand because I do specify the math library when calling gcc. When I comment the second line, it compiles/links correctly.

Here is the code:

// File wtf_sqrt.c
#include <math.h>

int main (int argc, char *argv[]) {
  int x = 3;  // Just an int...
  
  sqrt(3);  // This line works fine
  sqrt(x);  // But this one seems to give the linker trouble. Why?
  
  return 0;
}

Here is my compilation command:

gcc -lm -o wtf_sqrt wtf_sqrt.c

And here is the error returned:

/tmp/ccgQN7y7.o: In function `main':
wtf_sqrt.c:(.text+0x1c): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status

I use gcc version 7.5.0 on an Ubuntu 18.04 LTS. libc6-dev is installed (proof is, sqrt works when I use it as in the first line of main). The code was written in gedit, so it should not be a problem with a blank character. Not sure what other info I can give you…

At this point, I really suspect this is a problem with my config/distribution, but I wanted some external advice.

7
  • runs fine for me on cent os 7, may be the os you are using does not have it installed Commented Nov 12, 2020 at 10:55
  • 4
    Order of arguments might matter. Try moving -lm to after all of your source/object files. Commented Nov 12, 2020 at 10:56
  • 3
    sqrt(3); can be replaced by the compiler with the square root of 3. Or optimized out, since it is not doing anything. Commented Nov 12, 2020 at 10:58
  • 1
    Please see Link order of libraries Commented Nov 12, 2020 at 11:02
  • 1
    Libraries are searched where they appear on the command line, so if sqrt is not referenced by the files that precede it, it may not be included. Move the -lm option to the end and it should work. Commented Nov 12, 2020 at 11:03

3 Answers 3

1

This question actually has two parts, each of which is a duplicate of prior questions.

The fact that sqrt does not cause a link error when called with a constant argument is that the compiler evaluates it during compilation, as answered here, here, and here.

The fact that a link error is obtained even when -lm is included in the link is that -lm must be listed after modules that use the math library, as answered here, here, here, and here.

Sign up to request clarification or add additional context in comments.

Comments

1

As suggested in comments by users aragaer, Weather Vane and Tom Karzes, the problem was the position of -lm in the compilation command. I falsely supposed that providing it first would be the correct way since then the linker might know where to find the function, but instead I should have provided it last so that the linker would already know that I need sqrt from my program. In fact, it is not only the order of -l options that matter, but also the order of files (to be) compiled. So the correct command is:

gcc -o wtf_sqrt wtf_sqrt.c -lm

As explained by user Weather Vane, the first call to sqrt is probably replaced or removed due to an optimization, thus producing no error.

Comments

-1

The problem might be in the argument that sqrt() takes. This is the function in math.h header:

_Check_return_ _CRT_JIT_INTRINSIC double __cdecl sqrt(_In_ double _X);

As you can see, the parameter type the function takes is a double. In your first sqrt() call, you pass the value of 3 by just typing it inside the parenthesis - the compiler probably treats this 3 as a double and compiles successfully. But in the second call, you pas as an argument x, which is an int (and you don't convert it into double). As C doesn't support function overloading, the compiler can't find the sqrt function which takes an int parameter and it pops up an error. Casting x into double should fix the problem:

sqrt((double)x);

3 Comments

The function which I pasted in here is from windows header, and you're using Ubuntu. But even in Linux "math.h" header shows that "sqrt" takes a double as a parameter
Thank you for this suggestion. However, I forgot to mention that I already tried to cast x to double or even change the type of the variable, but it changes nothing. Plus, I found many examples on the web using sqrt on an int so I suppose it is not a problem.
As C doesn't support function overloading, the compiler can't find the sqrt makes no sense - C has implicit conversion, which occurs when calling a function.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.