Demi2012
Demi2012

Reputation: 90

Why no error without library specifiers in Linux?

I am currently a student and learning about operating systems and using Linux as the OS to practice on. When we got to multi-threaded applications and started to practice with them (mainly just pthread_create() and pthread_join() ), one of the most common errors the class got was that when compiling they used:

gcc -Wall homework.c

instead of:

gcc -Wall -lpthread homework.c

My question is why the compiler and linker don't throw an error when not compiled/linked with -lpthread specifier even though the functions used in the code require the pthread library. My instructor doesn't seem to know the reason either. Is it just the way the school has set up our system? Does that happen with all Linux environments? Why is no linker error thrown?

Upvotes: 4

Views: 134

Answers (2)

SergA
SergA

Reputation: 1174

Addition hypothesis to @FelixPalmen's answer. pthread can passed to linker as declared in gcc's specs. gcc can use built-in specs or reading it from file.

Experiment

By default on my system linker print errors while I try building sample without -lpthreads:

serga@XXXXX:~$ gcc ./thread.c -o thread
/tmp/ccHgCRzO.o: In function `main':
thread.c:(.text+0x29): undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status

First of all I detect which files gcc tries to use as spec:

serga@XXXXX:~$ strace gcc 2>&1 | grep spec
access("/usr/lib/gcc/i686-linux-gnu/5/specs", R_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gcc/i686-linux-gnu/5/../../../../i686-linux-gnu/lib/i686-linux-gnu/5/specs", R_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gcc/i686-linux-gnu/5/../../../../i686-linux-gnu/lib/specs", R_OK) = -1 ENOENT (No such file or directory)
access("/usr/lib/gcc/i686-linux-gnu/specs", R_OK) = -1 ENOENT (No such file or directory)

Then I create my own spec getting build-in one and place it into path that gotten in previous step:

    serga@XXXXX:~$ sudo gcc -dumpspecs >/usr/lib/gcc/i686-linux-gnu/5/specs

I inserted one by one -lpthread into *link:, *lib: and *libgcc: sections of spec-file. In all cases gcc can build program without explicit mention for pthread library:

serga@XXXXX:~$ gcc ./thread.c -o thread && echo "completed"
completed

Gotcha!!!

Detecting if gcc use any additional spec files

Need to see output of the next (I used gcc-5.1.0):

serga@XXXXX:~$ gcc -v 2>&1 | head -1
  • If gcc uses spec from specific file you'll see the next:

    Reading specs from /usr/lib/gcc/i686-linux-gnu/5/specs
    
  • Otherwise:

    Using built-in specs.
    

    You can see build-in specs doing this:

    serga@XXXXX:~$ gcc -dumpspecs
    

Detecting if linking with pthread is by default

Need to see inside gotten spec file any appearance of -lpthread in sections related to the linker.

Spec file reference

Upvotes: 0

user2371524
user2371524

Reputation:

Can't reproduce:

#include <pthread.h>

void *thread(void *arg)
{
    (void) arg;
    return 0;
}

int main(void)
{
    pthread_t t;
    pthread_create(&t, 0, thread, 0);
    return 0;
}

Trying to link without libpthread:

> gcc -Wall -o thread thread.c
/tmp/ccyyu0cn.o: In function `main':
thread.c:(.text+0x2e): undefined reference to `pthread_create'
collect2: error: ld returned 1 exit status

edit: you can check the symbols defined in a library with nm -D, e.g. in my case:

> nm -D /lib/x86_64-linux-gnu/libc.so.6 | grep pthread_create
> nm -D /lib/x86_64-linux-gnu/libpthread.so.0 | grep pthread_create
00000000000082e0 T pthread_create

(so pthread_create is not found in libc, but indeed in libpthread)

edit2: The only possible reason for the behavior you claim to observe would be that one of the libraries linked per default (libc, maybe libgcc) defines pthread_create. Then it would probably still be dependent on things only defined in libpthread. I now wonder whether this really is the case for some particular version. Please give feedback.

Upvotes: 2

Related Questions