Find the answer to your Linux question:
Page 1 of 2 1 2 LastLast
Results 1 to 10 of 12
Hello all! I'm trying to compile program with sqrt() function from math.h. Sometimes it compiles without -lm option, sometimes not. Here's 2 examples. First compiles fine, second outputs errors: Code: ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Dec 2005
    Posts
    96

    C, gcc, math.h and -lm


    Hello all!
    I'm trying to compile program with sqrt() function from math.h. Sometimes it compiles without -lm option, sometimes not. Here's 2 examples. First compiles fine, second outputs errors:

    Code:
    //program1.c
    #include<stdio.h>
    #include<math.h>
    
    int main(void)
    {
            printf("%.0f\n", sqrt(4));
    
            return 0;
    }
    $ gcc program1.c
    $ ./a.out
    2

    Now when I'm trying to compile a little bigger program I get these errors:
    Code:
    //program2.c
    #include <stdio.h>
    #include <math.h>
    
    int main(void)
    {
            float a,b,c,x1,x2;
    
            printf("Enter a\n");
            scanf("%d", &a);
            printf("Enter b\n");
            scanf("%d", &b);
            printf("Enter c\n");
            scanf("%d", &c);
            if ((b*b-4*a*c) < 0) 
                    printf("Error:discrimenant is negative. Solution cannot be found\n");
            else 
                    printf("x1= %d\n", ((-b+sqrt(b*b-4*a*c))/2*a)) && printf("x2= %d\n", ((-b-sqrt(b*b-4*a*c))/2*a));
    
            return 0;
    }
    $ gcc program2.c
    /tmp/ccEELoaA.o: In function `main':
    program2.c.text+0xe4): undefined reference to `sqrt'
    program2.c.text+0x13a): undefined reference to `sqrt'
    collect2: ld returned 1 exit status

    I really can't understand what's going on here...

  2. #2
    Just Joined! vigol's Avatar
    Join Date
    Jun 2008
    Location
    Uns Cigano from Vigol
    Posts
    24
    It's not related to "-lm".
    correct :
    c++ program2.c
    or
    g++ program2.c

    From GNU GCC Info: info (GNU texinfo) 4.11

    File: gcc-4.3.info, Node: Invoking G++, Next: C Dialect Options, Prev: Overall Options, Up: Invoking GCC
    3.3 Compiling C++ Programs

    C++ source files conventionally use one of the suffixes `.C', `.cc',
    `.cpp', `.CPP', `.c++', `.cp', or `.cxx'; C++ header files often use
    `.hh', `.hpp', `.H', or (for shared template code) `.tcc'; and
    preprocessed C++ files use the suffix `.ii'. GCC recognizes files with
    these names and compiles them as C++ programs even if you call the
    compiler the same way as for compiling C programs (usually with the
    name `gcc').

    However, the use of `gcc' does not add the C++ library. `g++' is a
    program that calls GCC and treats `.c', `.h' and `.i' files as C++
    source files instead of C source files unless `-x' is used, and
    automatically specifies linking against the C++ library. This program
    is also useful when precompiling a C header file with a `.h' extension
    for use in C++ compilations. On many systems, `g++' is also installed
    with the name `c++'.

    When you compile C++ programs, you may specify many of the same
    command-line options that you use for compiling programs in any
    language; or command-line options meaningful for C and related
    languages; or options that are meaningful only for C++ programs. *Note
    Options Controlling C Dialect: C Dialect Options, for explanations of
    options for languages related to C. *Note Options Controlling C++
    Dialect: C++ Dialect Options, for explanations of options that are
    meaningful only for C++ programs

  3. #3
    Just Joined!
    Join Date
    Dec 2005
    Posts
    96
    Well, it works. But why should I use C++ compiler to compile C program?
    And still why does first example work while second doesn't?

  4. $spacer_open
    $spacer_close
  5. #4
    Linux Guru Cabhan's Avatar
    Join Date
    Jan 2005
    Location
    Seattle, WA, USA
    Posts
    3,252
    I don't know what vigol is posting about (gcc is definitely the right program here, since it's a C program), but you are right that this is very strange behaviour.

    One possibility, which I have no evidence for, is that in the first case, you are calling sqrt(4). Well, because you are taking sqrt of a static number (as opposed to a variable), it is conceivable that gcc may optimize this away and just replace it with "2". So when the code gets to the linker, the sqrt() call is no longer there.

    As I say, this is just a guess, but it makes some sense to me.

  6. #5
    Just Joined!
    Join Date
    Dec 2005
    Posts
    96
    Yep. That's correct. Even if I comment out line with math.h the program still compiles. As soon as I put variable as actual argument, the program refuses to compile.

    g++ can compile my program in both cases with no problems at all, thou...

    It's strange that no book (well, at least books that I have seen) addresses the issue with -lm option on linux. I found this solution occasionally on some forums.

  7. #6
    Just Joined! vigol's Avatar
    Join Date
    Jun 2008
    Location
    Uns Cigano from Vigol
    Posts
    24
    Your Question was about C and I solved it by C++ !!
    I'd have this problem before, and solved by this way!
    Frankly, I didn't try to find the origin problem.
    You can trace these site for finding (maybe) a practical/theorical solution.
    1. C programming.com - Your Resource for C and C++ Programming
    2. GCC, the GNU Compiler Collection - GNU Project - Free Software Foundation (FSF)
    2.1. GCC online documentation - GNU Project - Free Software Foundation (FSF)
    2.2. GCC Frequently Asked Questions - GNU Project - Free Software Foundation (FSF)
    2.3. HomePage - GCC Wiki
    2.4. Links and Selected Readings - GNU Project - Free Software Foundation (FSF)

    If you find it, inform us too.

  8. #7
    Linux Guru
    Join Date
    Nov 2007
    Location
    Córdoba (Spain)
    Posts
    1,513
    I am not sure and not inclined to search about the thing, but I think that the issue of the original poster is related to what Cabhan said. I think it's gcc making some early substitution that prevents the need to link.

    Indeed, it's something we can check easily:

    Code:
    $ gcc test.c 
    $ ./a.out 
    2
    $ ldd a.out
            linux-vdso.so.1 =>  (0x00007fffca1fd000)
            libc.so.6 => /lib/libc.so.6 (0x00007f38c1b18000)
            /lib64/ld-linux-x86-64.so.2 (0x00007f38c1e6d000)
    As you can see, libm is not there. In the contrary, if you do this, then it's there:

    Code:
    $ gcc test.c  -lm
    $ ldd a.out
            linux-vdso.so.1 =>  (0x00007fffe9ffe000)
            libm.so.6 => /lib/libm.so.6 (0x00007f93e1b23000)
            libc.so.6 => /lib/libc.so.6 (0x00007f93e17ce000)
            /lib64/ld-linux-x86-64.so.2 (0x00007f93e1da6000)
    If you change sqrt(4) by sqrt(a) and define int a=4 elsewhere, then you need to link against the library, because no substitution can be done (my guess is that it would make the thing much more complex, since there should be lots of checks to ensure that a is a constant).

    Not too much people would have noticed this because:

    1.- when you use libm, you usually link against libm by using -lm
    2.- no one inserts things like sqrt(4) in a program

    Go figure when this has been introduced...



    The other thing that vigol is speaking about is completely unrelated, which is the capability of g++ to automatically link whatever is needed. You can check with a simple c++ program:

    Code:
    #include<iostream>
    #include<math.h>
    
    int main(void)
    {
      int a;
      std::cout << sqrt(a);
      return 0;
    }
    Code:
    $ g++ test.cpp
    $ ldd ./a.out 
            linux-vdso.so.1 =>  (0x00007fff4d7fe000)
            libstdc++.so.6 => /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.1/libstdc++.so.6 (0x00007fc745205000)
            libm.so.6 => /lib/libm.so.6 (0x00007fc744f82000)
            libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007fc744d6b000)
            libc.so.6 => /lib/libc.so.6 (0x00007fc744a16000)
            /lib64/ld-linux-x86-64.so.2 (0x00007fc745510000)
    On the C case, it compiles without lm only if a constant is specified, otherwise you need -lm. On C++, -lm is assumed when needed, and it compiles linking it without a need for -lm on command line. ldd shows it very clearly.

    So, both issues are not related really. And C++ has nothing to do with the problem of the original poster.

    To be sure about the substitution thing, the best way would be to either ask on the relevant mailing lists or look for changelogs (which can take quite a bit of time, considering that that might have been around for years without me noticing it).

    For the rest, you only need to know that gcc needs -lm (for real life cases where you will rarely use a constant), and g++ does not need it because it will like automatically if needed.

  9. #8
    Just Joined!
    Join Date
    Dec 2005
    Posts
    96
    THX for the input all! Now I've got clear understanding of what's going on.

    you only need to know that gcc needs -lm [...] and g++ does not need it because it will like automatically if needed.
    That's will make life much easier, if gcc would do the same.

  10. #9
    Just Joined!
    Join Date
    May 2005
    Posts
    48
    void_false
    For better results, on the quadradic equation in C the placeholder for float is &#37;f. (In the scanf and printf)
    hth && gl

  11. #10
    Just Joined!
    Join Date
    Dec 2005
    Posts
    96
    Quote Originally Posted by waka View Post
    void_false
    For better results, on the quadradic equation in C the placeholder for float is %f. (In the scanf and printf)
    hth && gl
    That was just example from the book I'm studying at the time.

Page 1 of 2 1 2 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •