Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What default libraries are taken while compiling C project with GCC

Tags:

c

gcc

I have simple application:

#include <stdio.h>
int main( int argc, char ** argv )
{
    printf( "hello");
    exit( 0 );
}

When I compile it with command

gcc -c count_words.c

I have warning:

warning: incompatible implicit declaration of built-in function ‘exit’ [enabled by default]
     exit( 0 );

I was trying to find where exit() function is defined. And found that it is defined in stdlib.h. But it is not included in my project and no additional libs defined in compile command.

Correct me if I'm wrong, but looks like gcc takes some libs as default. What are these libs and is it possible to tell gcc not include them?

Why compiler is not happy regarding exit(0) assuming that it somehow includes stdlib.h as default?

like image 441
vico Avatar asked Sep 26 '22 17:09

vico


2 Answers

Let's take your example:

#include <stdio.h>

int main( int argc, char ** argv )
{
    printf("hello\n");
    exit(56);
}

Although we get a warning on compilation:

~$ gcc test.c -o test
test.c: In function ‘main’:
test.c:6:5: warning: implicit declaration of function ‘exit’ [-Wimplicit-function-declaration]
     exit(56);
     ^
test.c:6:5: warning: incompatible implicit declaration of built-in function ‘exit’
test.c:6:5: note: include ‘<stdlib.h>’ or provide a declaration of ‘exit’

Anyway, I think you have tried to run it and make sure it works:

~$ ./test
hello
~$ echo $?
56

@Mat was right when he said that:

You're mixing up including headers and linking to libraries. Those are two completely different things

The C compiler and linker are totally separate tools. Let's look on this. Actually, this program depends on the standard C library (as all programs if you didn't pass -nostdlib to compiler) and a couple of system libraries (like loader and vdso). You may see it with:

~$ ldd test
    linux-vdso.so.1 (0x00007fff1b128000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f804389f000)
    /lib64/ld-linux-x86-64.so.2 (0x0000557744537000)

These three library is a minimal set for any program. The exit function is defined in the standard library or libc.so.6 in our case. Now let's look on the compilation process in verbose mode. You can achieve this by the passing -v or --verbose option to compiler:

gcc test.c -o test --verbose

If you will execute this, you will find lines like these:

#include <...> search starts here:
/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include
/usr/local/include
/usr/include

So, compile knows where to search header files for stdlib and it starts to search it to find declaration for non-local functions. Note that it searches only in header files which are included in your source code file. It can find printf declaration in thestdio.h, but can't locate declaration of the exit.

After this step, the compile starts to link your program with libraries:

/usr/libexec/gcc/x86_64-redhat-linux/5.3.1/collect2 ... -lc ...

Where collect2 is gcc util which tries to link your program with lc which is standard C library. Note that the process consists from two steps: compilation and linking. That's why your program works.

Additionally, gcc supports -M option which will tell you about dependencies of the main file. So, if you will execute it, you will see the set of header files including stdio.h, but not stdlib.h:

$ gcc -M test.c
test.o: test.c /usr/include/stdc-predef.h /usr/include/stdio.h \
 /usr/include/features.h /usr/include/sys/cdefs.h \
 /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
 /usr/include/gnu/stubs-64.h \
 /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h \
 /usr/include/bits/types.h /usr/include/bits/typesizes.h \
 /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
 /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stdarg.h \
 /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h

Or even better, try to pass -E option to gcc:

$ gcc -E test.c

and you will see result right after the first stage - preprocessing stage. I think it is the easiest way to understand why you are getting this warning.

like image 150
0xAX Avatar answered Sep 29 '22 06:09

0xAX


assuming that it somehow includes stdlib.h as default?

It simply doesn't. That wouldn't be standards-compliant.

So, when you use exit, it has never been declared, so there's you implicit declaration upon usage. However, the fact to you implement exit nowhere else will only become a problem at the final linkage.

Now, GCC knows damn well that you are about to get into trouble, so it warns you.

Simply actually include stdlib.h and you should be fine.

like image 37
Marcus Müller Avatar answered Sep 29 '22 05:09

Marcus Müller