Problem in compiling C function with threading on Fedora - c

When I try to compile a C-program with multithreading in Fedora, I get the following error.
The file name is abc.c
abc.c:(.text+0x39): undefined reference to `pthread_create'
abc.c:(.text+0x61): undefined reference to `pthread_create'
abc.c:(.text+0x79): undefined reference to `pthread_join'
abc.c:(.text+0x8d): undefined reference to `pthread_join'
I checked in /usr/include and I found that pthread.h is present. Also I tried copying pthread.h to the same directory as abc.c
How do I resolve these linking errors?

As pointed out by George you must link with the thread library
gcc -o abc abc.c -pthread
The reason you are getting those errors is because during the linking stage the compiler tries to fill in all the slots where it had placed placeholders for method calls that it knew were defined but currently did not know their locations because the appropriate library had not been linked yet. As pointed out by caf using the -pthread flag in both compiling and linking stages allows for the compiler to make smarter choices about what it needs to use to be thread-safe in certain conditions.

Related

Why do you need '-lpthread'?

So my questions is: Why do you need '-lpthread' at the end of a compiling command?
Why does this command work:
gcc -o name name.c -lpthread
but this won't:
gcc -o name name.c
I am using the pthread.h library in my c code.
I already looked online for some answers but didn't really find anything that answered it understandably
pthread.h is not a library it is just a header file which gives you declaration (not the actual body of function) of functions which you will be using for multi-threading.
using -libpthread or -lpthread while compiling actually links the GCC library pthread with your code. Hence the compiler flag, -libLIBRARY_NAME or -lLIBRARY_NAME is essential.
If you don't include the flags -l or -lib with LIBRARY_NAME you won't be able to use the external libraries.
In this case, say if you are using functions pthread_create and pthread_join, so you'll get an error saying:
undefined reference to `pthread_create'
undefined reference to `pthread_join'
The -l options tells the linker to link in the specified external library, in this case the pthread library.
Including pthread.h allows you to use the functions in the pthread library in you code. However, unlike the functions declared in places like studio.h or stdlib.h, the actual code for the functions in pthread.h are not linked in by default.
So if you use functions from this library and fail to use -lpthread, the linking phase will fail because it will be unable to find functions in the library such as pthread_create, among others.

error when trying to link with static c standard library

My OS is ubuntu 14.04 32bit and my source program test.c is :
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("test.");
return;
}
I compile it with command :
gcc -S test.c
which output as a test.s file. I assemble it with command :
as -o test.o test.s
then I want to link it with c standard library statically. I searched for libc.a file , located it at /usr/lib/i386-linux-gnu/libc.a. so I tried to link it with command:
ld test.o /usr/lib/i386-linux-gnu/libc.a
but comes out with a lot of error message:
ld: warning: cannot find entry symbol _start; defaulting to 0000000008048210
/usr/lib/i386-linux-gnu/libc.a(backtrace.o): In function `backtrace_helper':
(.text+0x20): undefined reference to `_Unwind_GetIP'
/usr/lib/i386-linux-gnu/libc.a(backtrace.o): In function `backtrace_helper':
(.text+0x45): undefined reference to `_Unwind_GetGR'
/usr/lib/i386-linux-gnu/libc.a(backtrace.o): In function `backtrace_helper':
(.text+0x50): undefined reference to `_Unwind_GetCFA'
/usr/lib/i386-linux-gnu/libc.a(backtrace.o): In function `__backtrace':
(.text+0xb1): undefined reference to `_Unwind_Backtrace'
/usr/lib/i386-linux-gnu/libc.a(iofclose.o): In function `_IO_new_fclose':
(.text+0x1b1): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iofclose.o):(.eh_frame+0x167): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(iofflush.o): In function `_IO_fflush':
(.text+0xd7): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iofflush.o):(.eh_frame+0xdf): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(iofputs.o): In function `_IO_fputs':
(.text+0xf9): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iofputs.o):(.eh_frame+0xdf): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(iofwrite.o): In function `_IO_fwrite':
(.text+0x139): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iofwrite.o):(.eh_frame+0xdf): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(iogetdelim.o): In function `_IO_getdelim':
(.text+0x285): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(iogetdelim.o):(.eh_frame+0xdf): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(wfileops.o): In function `_IO_wfile_underflow':
(.text+0x5fc): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(wfileops.o):(.eh_frame+0x137): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(fileops.o): In function `_IO_new_file_underflow':
(.text+0x40b): undefined reference to `_Unwind_Resume'
/usr/lib/i386-linux-gnu/libc.a(fileops.o):(.eh_frame+0x1b3): undefined reference to `__gcc_personality_v0'
/usr/lib/i386-linux-gnu/libc.a(strtof_l.o): In function `____strtof_l_internal':
(.text+0xbc6): undefined reference to `__divdi3'
/usr/lib/i386-linux-gnu/libc.a(strtof_l.o): In function `____strtof_l_internal':
(.text+0xc08): undefined reference to `__moddi3'
/usr/lib/i386-linux-gnu/libc.a(strtof_l.o): In function `____strtof_l_internal':
(.text+0x249d): undefined reference to `__divdi3'
/usr/lib/i386-linux-gnu/libc.a(strtod_l.o): In function `____strtod_l_internal':
(.text+0xcc9): undefined reference to `__divdi3'
/usr/lib/i386-linux-gnu/libc.a(strtod_l.o): In function `____strtod_l_internal':
(.text+0xd0b): undefined reference to `__moddi3'
...
...
My question is, why these error messages ? I'm trying to learn how the compiling system works, so instead of knowing how to solve this problem I 'm more desiring to know how it comes this way. It seems that the static C library depends on other libraries, why and what are those libraries ?
EDIT:
I'm doing this because I want to know how things work so I'd rather avoid the gcc script.
You also need crt0 startup object files (in addition of static libc.a), which notably are defining the _start entry point (in your ELF executable) and contain ABI specific (prologue and epilog) code to call your main (and finally process atexit(3) registered handlers and stdio flushing). The low-level libgcc is also needed. Details are complex and implementation specific. To understand them, compile your test code as
gcc -v -static test.c -o mytest
(avoid calling an executable test because it would collide with /usr/bin/test or with the builtin of your shell)
In practice, better at least link with gcc
If you are curious, take advantage that Linux is mostly free software and study the source code (e.g. of GCC, of the C standard library, of binutils, etc...). You might find musl-libc interesting.
I'd rather avoid the gcc script
Technically, gcc is not a script but a driver program (see gcc/gcc.c in the source code of GCC). But it will run ld which indeed runs some linker scripts. The actual compilation is done by cc1 which is started by the gcc program.
You must also link the gcc intrinsic library. The easiest way to do this is to use the gcc front-end to compile and link with the -static option:
gcc -static -o test test.c
If you insist on compiling from assembly, you can do this:
gcc -static -o test test.s
Static linking may not be supported on your system.
EDIT: giving gcc the -v option will tell you what commands it executes.

Compiling using arm-none-eabi-gcc and linking library liba.a error

I am compiling a hello world program in C on a 64-bit Linux machine. I am using a GCC ARM embedded toolchain to cross compile my program on a FOX G20 V board with an ATMEL AT91SAM9G20 processor.
On the first take, I had a few errors when compiling because the program didn't recognize the printf, return etc. functions (the standard C functions). So I decided to make the link between the functions, which I believe are defined in the libc.a library (correct me if I'm wrong), by doing arm-none-eabi-gcc -o hello hello.c libc.a but the outcome still results in errors:
libc.a(lib_a-exit.o): In function `exit':
exit.c:(.text.exit+0x16): undefined reference to `_exit'
libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'
libc.a(lib_a-writer.o): In function `_write_r':
writer.c:(.text._write_r+0x10): undefined reference to `_write'
libc.a(lib_a-closer.o): In function `_close_r':
closer.c:(.text._close_r+0xc): undefined reference to `_close'
libc.a(lib_a-fstatr.o): In function `_fstat_r':
fstatr.c:(.text._fstat_r+0xe): undefined reference to `_fstat'
libc.a(lib_a-isattyr.o): In function `_isatty_r':
isattyr.c:(.text._isatty_r+0xc): undefined reference to `_isatty'
libc.a(lib_a-lseekr.o): In function `_lseek_r':
lseekr.c:(.text._lseek_r+0x10): undefined reference to `_lseek'
libc.a(lib_a-readr.o): In function `_read_r':
readr.c:(.text._read_r+0x10): undefined reference to `_read'
collect2: error: ld returned 1 exit status
I'm really unsure as to why the program still does not recognize the standard functions even though I've linked the library to the application. If anyone has a reason as to why, or a solution as to how I can fix this problem, I would be very grateful.
UPDATE
I've downloaded the glibc library from here. I've compiled and created a static library from the syscalls.c library that I found in newlib-2.1.0/libgloss/arm and when I link the library to my application code, I still get the same error.
Try executing this:
arm-none-eabi-gcc --specs=rdimon.specs -lgcc -lc -lm -lrdimon -o hello hello.c
Your toolkit seems to provide the librdimon.a, a library which provides the basic standard C functions.
I got this error because my binary cannot fit the ROM.
My first error was:
address 0x34000 of arm_flash.elf section `.mmu_tbl' is not within region `ps7_ram_0`
Then I've got the same list of undefined reference errors.
I need to reduce the binary size, by removing new keywords, and all dynamic memory allocation from my C++ code.

GCC libm not working

I have a c program that calls sin, cos, and acos. When I compile I get the following errors:
/tmp/ccDfW98S.o: In function `zip_search':
main.c:(.text+0xf30): undefined reference to `sin'
main.c:(.text+0xf45): undefined reference to `sin'
main.c:(.text+0xf66): undefined reference to `cos'
main.c:(.text+0xf7b): undefined reference to `cos'
main.c:(.text+0xf9c): undefined reference to `cos'
main.c:(.text+0xfc6): undefined reference to `acos'
collect2: ld returned 1 exit status
I know this is common when you don't use the -lm gcc flag. I AM using this flag. I'm calling GCC like this:
gcc -o zipcode-server -lm main.c
When I compile on one of my computers this works fine. The only difference that I can think of is that this isn't working on x86_64 and the computer it does work on is i686. Both are Ubuntu. The file libm.a is present on the computer it isn't working on and I don't get any errors saying it can't be found. What could be causing this?
You should put -lm after main.c
In general, if you have multiple libraries, they should be written in order of their usage. For example, if library A uses library B, you should have -lA -lB.
In your case, the object file that is the result of compilation of main.c uses library m and therefore -lm should come after it.
For the curious, this is mostly for efficiency reasons. With this scheme, the linker can resolve currently unknown symbols with every new library seen in the argument list, and picking up new unknown symbols from that library on the way. This means that the linker can visit the libraries one by one, and therefore match the unknown symbols against a small number of symbols provided by each library.
On the contrast, the linker could load in symbols from all libraries at once, and then start matching unknown symbols. In that case however, the linker needs to deal with a much greater number of symbols, increasing both the memory footprint and the execution time of the linker.
Since the libraries could always be declared to the linker in the proper order of their dependencies1, there is no reason for the linker to choose the inefficient way.
1 Libraries normally have a one-way relationship, in the sense that one uses the other. Circular dependencies between libraries is rare, if at all existing, but it could still be used with this model by repeating certain libraries to be reinspected.

GCC -nostdlib fails with undefined reference to `__libc_csu_fini'

I provide the linker with my files: ld-2.7.so, libc-2.7.so and crt1.o but it fails to compile successfully. Is it possible to link to a different glibc from the default one ?
(Static compilation or installing a separate glibc is not an option.)
gcc -Wl,-dynamic-linker,ld-2.7.so,libc-2.7.so,crt1.o -nostdlib program.c
crt1.o: In function `_start':
(.text+0x12): undefined reference to `__libc_csu_fini'
crt1.o: In function `_start':
(.text+0x19): undefined reference to `__libc_csu_init'
/tmp/user/1000/ccauFlwt.o: In function `findsize':
program.c:(.text+0x21): undefined reference to `stat'
/tmp/user/1000/ccauFlwt.o: In function `findtime':
program.c:(.text+0x4c): undefined reference to `stat'
collect2: ld returned 1 exit status
I found out how to do it:
rpath specifies where the provided libraries are located. This folder should contain: libc.so.6, libdl.so.2, libgcc_s.so.1 and maybe more. Check with strace to find out which libraries your binary file uses.
ld.so is the provided linker
gcc -Xlinker -rpath=/default/path/to/libraries -Xlinker -I/default/path/to/libraries/ld.so program.c
As #onemasse said, you also need header files compatible with that version of libc. Between glibc versions things still work anyway though, but this can not relied upon.
Otherwise, I would suggest you use export LD_PRELOAD_PATH to wherever your other libc is before starting the new library.
But what you really is after, is to cross-compile in linux, for linux, but with another libc.
Have a look at crosstool.
If you want to link to another libc than the one provided by the system you also need to compile your program with header files compatible with that version of libc.
Also, I'm not familiar with the option "-dynamic-linker". It's not in the man page for gcc. I really can't work out what you're trying to do.
Maybe you should try this instead and work from there:
gcc -ldl program.c -o program
You normally don't have to explicitly link with "libc" or "crt1.o".

Resources