a gcc sqrt function bug? - c

The following program cannot compile in gcc. But it compiles OK with g++ and MSC++ with .c extension.
#include <math.h>
#include <stdio.h>
int main()
{
double t = 10;
double t2 = 200;
printf("%lf\n", sqrt(t*t2));
return 0;
}
My system is CentOS, the version info.
> gcc --version
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
The error info:
> gcc test.c
/tmp/ccyY3Hiw.o: In function `main':
test.c:(.text+0x55): undefined reference to `sqrt'
collect2: ld returned 1 exit status
Is this a bug?
Any one can do a test for me?

Have you linked the math library?
gcc -lm test.c -o test

Add the math library with flag -lm
> gcc test.c -lm

Try gcc -lm test.c -o test
For gcc, you need to tell it to link the math library in, by adding -lm
to your gcc call.

Everybody has been saying this, but I will too. You have to "tell" gcc to link to the math library. When you compile, instead of saying gcc test.c, you have to say gcc -lm test.c. I wish that I could just #include math.h and not have to do anything else.

The thing is, gcc -lm test.c -o test won't work because gcc will treat the -lm as a compiler and not a linker option. You need to put the -lm at the end of the command instead, i.e. gcc -o test test.c -lm

Related

Undefined reference error but symbol existing in the library

I get an undefined reference error for the example below. I have seen lots of questions that relate to this issue but believe I gave a stripped, reproducible, conceptual example as opposed specific issues in other questions,
dynlib.h:
void printMe_dyn();
dynlib.c:
#include <stdio.h>
#include "dynlib.h"
void printMe_dyn() {
printf("I am execuded from a dynamic lib");
}
myapp.c:
#include <stdio.h>
#include "dynlib.h"
int main()
{
printMe_dyn();
return 0;
}
Build steps:
gcc -Wall -fpic -c dynlib.c
gcc -shared -o libdynlib.so dynlib.o
gcc -Wall -L. -ldynlib myapp.c -o myapp
Error:
/tmp/ccwb6Fnv.o: In function `main':
myapp.c:(.text+0xa): undefined reference to `printMe_dyn'
collect2: error: ld returned 1 exit status
Proof that the symbol is in the library:
nm libdynlib.so | grep printMe_dyn
00000000000006e0 T printMe_dyn
Am I using the correct compiler flags for building the dynamic
library?
Is the proof I've presented really an unambiguous proof?
What other approach could be taken to diagnose the issue?
The order of appearance of libraries matter.
To quote the online gcc manual
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded.
You should be changing your compilation statement to
gcc -o myapp -Wall -L. myapp.c -ldynlib
to tell gcc to search for the symbols used in (compiled) myapp.c to be present in dynlib.
Just as additional notice. The same behavior one may obtain when the library has been built by gcc and linked to the c++ project. Like follows:
gcc -Wall -fpic -c dynlib.c
gcc -shared -o libdynlib.so dynlib.o
g++ -o myapp -Wall -L. myapp.cpp -ldynlib
In such case the reason is name-mangling used by g++. To have it turned off one must wrap C-function prototypes by extern "C" within C-library. For example like follows:
dynlib.h:
#ifdef __cplusplus
extern "C"{
#endif
void printMe_dyn();
#ifdef __cplusplus
}
#endif
The order of libraries in linker command line matters. Fix:
gcc -o myapp -Wall -L. myapp.c -ldynlib

Linking partially static and partially dynamic in GCC

I'm trying to compile a very simple (as simple as hello world) C program using both dynamic and static linking with GCC. I want to know how to do this in general, so my minimal test example is simply trying to link libc as static and libm dynamically.
I've come across at least the following other questions regarding the same topic:
GCC: static linking only some libraries
Static link of shared library function in gcc
Some of the answers therein suggest things such as using -Wl,-Bstatic and -Wl,-Bdynamic to specify which libraries are respectively static and dynamic. Also suggested is among others simply specifying the full path of the static library to link against.
I've tried several of these suggestions, and variants thereof. I don't understand the error message it gives me. I know what PIE is, but I don't see how it relates to what I'm trying to do.
Here are some failed attempts:
$ gcc test.c /usr/lib64/libc.a
linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
urned 1 exit status
$ gcc test.c -Wl,-Bdynamic -lm -Wl,-Bstatic -lc
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
$ gcc -Wl,-Bdynamic -lm -Wl,-Bstatic -lc test.c
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
$ gcc -Wl,-Bstatic -lc -Wl,-Bdynamic -lm test.c
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink with -pie
collect2: error: ld returned 1 exit status
Compiling just with no arguments, and with -static work fine, but I need partial static compilation:
$ gcc test.c -lm
$ gcc -static test.c -lm
However, the following fails too:
$ gcc test.c /usr/lib64/libc.a /usr/lib64/libm.a
I've come across a similar error in this post:
C++ Statically linked shared library
However the answers do not seem to apply to my problem.
The program I'm trying to compile is simply (as test.c):
#include <stdio.h>
#include <math.h>
int main(int argc, char **argv)
{
int i = 0;
for(i = 0; i < 65535; i++) {
printf("%f\n", sinf(i));
printf("%f\n", cosf(i));
printf("%f\n", tanf(i));
printf("%f\n", sqrtf(i));
}
return 0;
}
EDIT: Please note that the program must be complex enough to actually require libm, otherwise linking attempts might give false positives if libm is not really needed. In my original test.c example, I used only sinf() to a constant value, which made the compiler optimize out the sinf() call completely.
I'm using:
$ gcc --version
gcc (Gentoo 4.7.3-r1 p1.4, pie-0.5.5) 4.7.3
The following worked for me
ln -s `gcc -print-file-name=libc.a`
gcc -static-libgcc -L. -lc test.c
Then ldd a.out gives:
not a dynamic executable
Edit:
The OP wants to link one library dynamically and another statically. He have the example of linking libc statically and libm dynamically. That particular case I have not been able to achieve. However, the opposite is possible i.e. linking libc dynamically and libm statically.
ln -s `gcc -print-file-name=libm.a`
gcc test.c -L. -lm
then ldd a.out gives
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x41960000)
/lib/ld-linux.so.2 (0x4193d000)
Note that the link order matters.e.g gcc -L. -lm test.c does not work.
This works with other libraries as well. For example gomp
gcc -fopenmp test.c
ldd shows libgomp.so.1. We can link it statically like this
ln -s `gcc -print-file-name=libgomp.a`
gcc -L. -fopenmp test.c
Now ldd a.out does not show libgomp.so.1. But in this case pthreads is still linked dynamically. To link pthreads statically requires that libc be linked statically as well.

compiling a c program to use in python code

I have a c program that I need to compile and use in the middle of a python code. it is not c++ program so I assume I should change this syntax for compiling because I get a lot of errors related to not having "main()" in the program which is just because it is a c (not c++)for a x86_64 Mac system?
how should I change this syntax for a program.c code?
g++ -o program.x program.c
Your C code should be compiled into a shared library:
gcc -shared -o program.so -Wall -Wextra -fPIC -O2 -DNDEBUG program.c
And then you can use ctypes module to invoke functions in your library from Python.

how to get the x to the pow y in C under c99 standard

I have #include<math.h>,
and I tried to use pow(x, y) and powf(x, y).
but it seems neither of them are under c99 standard.
and I use the command gcc -std=c99 test.c -o test to compile.
what function there exists I can use?
For histerical reasons, the math library is not bundled in with the rest of the Standard Library. You have to manually add it to the compilation with the -lm option to gcc.
gcc -std=c99 test.c -o test -lm
Did you link with the math lib?
gcc -std=c99 test.c -o test -lm

Oh no, not another Undefined Reference question!

Unfortunately yes.
I have my shared library compiled, the linker doesn't complain about not finding it but still I get undefined reference error. Thinking that I might be doing something wrong I did a little research and found this nice, simple walkthrough:
http://www.adp-gmbh.ch/cpp/gcc/create_lib.html
which I've followed to the letter but still I get:
$ gcc -Wall main.c -o dynamically_linked -L.\ -lmean
/tmp/ccZjkkkl.o: In function `main':
main.c:(.text+0x42): undefined reference to `mean'
collect2: ld returned 1 exit status
This is pretty simple stuff so what's going wrong?! Is there something in my set up that might need checking/tweeking?
GCC 4.3.2 Fedora 10 64-bit
Change:
$ gcc -Wall main.c -o dynamically_linked -L.\ -lmean
to:
$ gcc -Wall main.c -o dynamically_linked -L. -lmean
You probably meant to do this:
$ gcc -Wall main.c -o dynamically_linked -L./ -lmean
which is OK, but the trailing / is redundant
How was the library created? Libtool?
Show us an ls -l of your current directory, and look at what gcc -v <rest of your command> says (that gives details of what gcc is doing).

Resources