If we have a function foo() which has same prototype in two different libraries with different implementation and if we include only single header file (which has declaration of function), what happens if we try to compile or execute the program at compile or runtime ?
Per your tags, you are asking about the linkage of static libraries. The linker
doesn't know or care what source language(s) its input files were compiled
from. The C language is immaterial to the question, but I'll use C for illustration.
Read the Stackoverflow
tag Wiki about static libraries and it will explain that linking
your program with a static library is exactly the same as linking your program
with 0 or more of the object files that are archived in the static library - namely
the 0 or more object files that the linker needs to provide definitions for otherwise
unresolved symbol-references in the program.
Once the linker has found an object file p.o file in a static library libx.a that provides it
with a definition for some symbol foo that the program refers to, it will link
the object file libx.a(p.o) into the program to resolve foo. It will not
try to find any other definition of foo in any other object file q.o file in any other
static library liby.a that comes after libx.a in the linkage.
So if there is any other object file q.o in any other static library liby.a
that comes later in the linkage than libx.a that also contains a definition of
foo, that object file liby.a(q.o) will not even be linked into the program
unless the linker needs it provide a definition of some other symbol bar
that the program refers to. Assuming that is not the case, liby.a(q.o) might
as well not exist, for linkage purposes.
The linker will not link multiple definitions of the same symbol from libx.a(p.o) and liby.a(q.o) if it
does not need to. It will link the first object file, libx.a(p.o), that defines foo
into the program, and then it is done with defining foo.
Here's an illustration of that:
main.c
extern void foo(void);
extern void bar(void);
int main(void)
{
foo();
bar();
return 0;
}
p.c
#include <stdio.h>
void foo(void)
{
printf("%s %s %s\n",__func__,"from",__FILE__);
}
q.c
#include <stdio.h>
void foo(void)
{
printf("%s %s %s\n",__func__,"from",__FILE__);
}
r.c
#include <stdio.h>
void bar(void)
{
printf("%s %s %s\n",__func__,"from",__FILE__);
}
Function foo is defined in p.c and also in q.c.
Compile all the .c files to .o files:
$ gcc -c main.c p.c q.c r.c
Create three static libraries, one from each of p.o, q.o, r.o:
$ ar rcs libx.a p.o
$ ar rcs liby.a q.o
$ ar rcs libz.a r.o
Then link a program, inputting libx.a before liby.a:
$ gcc -o prog main.o libz.a libx.a liby.a -Wl,-trace-symbol=foo
/usr/bin/ld: main.o: reference to foo
/usr/bin/ld: libx.a(p.o): definition of foo
The diagnostic linkage option -Wl,-trace-symbol=foo asks the linker to tell
us the names of the files that are linked into prog where it finds unresolved references to foo and
also the name of the file where foo is defined. You see that foo is referenced in main.o
and the definition provided by libx.a(p.o) is linked. The other definition of foo in
liby.a(q.o) is not linked. This linkage is exactly the same as
gcc -o prog main.o r.o p.o
which contains only the definition of foo from p.o, as the program
shows:
$ ./prog
foo from p.c
bar from r.c
Now relink prog, this time with liby.a before libx.a:
$ gcc -o prog main.o libz.a liby.a libx.a -Wl,-trace-symbol=foo
/usr/bin/ld: main.o: reference to foo
/usr/bin/ld: liby.a(q.o): definition of foo
This time, the definition of foo was linked from liby.a(q.o). This linkage is exactly the same as:
gcc -o prog main.o r.o q.o
which contains only the definition of foo from q.o, as the program
shows:
$ ./prog
foo from q.c
bar from r.c
The linker does not care how many definitions of foo you offer it in
different object files in different static libraries. It only cares that
if foo is referenced in the program, then foo is defined, exactly once,
by the files that it links into the program.
If you compel the linker to link files into the program that contain more
than one definition of foo, then by default and normally the linker will
give you a multiple definition error and the linkage will fail, because
there cannot be more than one definition of foo in a program. Here's an
illustration of that:
qr.c
#include <stdio.h>
void foo(void)
{
printf("%s %s %s\n",__func__,"from",__FILE__);
}
void bar(void)
{
printf("%s %s %s\n",__func__,"from",__FILE__);
}
Compile that file:
$ gcc -c qr.c
Archive qr.o in a new static library:
$ ar rcs libyz.a qr.o
The object file libyz.a(qr.o) defines both foo and bar. So we can link
our program like:
$ gcc -o prog main.o libyz.a -Wl,-trace-symbol=foo,-trace-symbol=bar
/usr/bin/ld: main.o: reference to foo
/usr/bin/ld: main.o: reference to bar
/usr/bin/ld: libyz.a(qr.o): definition of foo
/usr/bin/ld: libyz.a(qr.o): definition of bar
And it runs like:
$ ./prog
foo from qr.c
bar from qr.c
But if we attempt to link it like:
$ gcc -o prog main.o libx.a libyz.a -Wl,-trace-symbol=foo,-trace-symbol=bar
/usr/bin/ld: main.o: reference to foo
/usr/bin/ld: main.o: reference to bar
/usr/bin/ld: libx.a(p.o): definition of foo
/usr/bin/ld: libyz.a(qr.o): in function `foo':
qr.c:(.text+0x0): multiple definition of `foo'; libx.a(p.o):p.c:(.text+0x0): first defined here
/usr/bin/ld: libyz.a(qr.o): definition of bar
collect2: error: ld returned 1 exit status
there is a multiple definition of foo. That is because:
The linker needed a definition of foo and found the first one in libx.a(p.o);
so it linked that file into the program. It won't search for any other one.
The linker needed a definition of bar and found the first one in libyz.a(qr.o);
so it linked that file into the program. It won't search for any other one.
But libyz.a(qr.o) contains another definition of foo as well as a definition
of bar. So now two definitions of foo have been linked, and that is an error.
I said that you'll get a multiple definition error by default if you make the
linker attempt to link into the program more than one file that defines a symbol.
But you can avoid that by telling the linker than the symbol is weakly defined, provided that your linker understands this concept (as the GNU and Apple linkers do).
GCC compilers support a non-standard language extension, the __attribute__ syntax
that you can use to communicate to the linker that a symbol definition is weak.
Here's an illustration of that:
qr.c (2)
#include <stdio.h>
void __attribute__((weak)) foo(void)
{
printf("%s %s %s\n",__func__,"from",__FILE__);
}
void bar(void)
{
printf("%s %s %s\n",__func__,"from",__FILE__);
}
Recompile:
$ gcc -c qr.c
Delete libyz.a and recreate it:
$ rm libyz.a
$ ar rcs libyz.a qr.o
Retry the linkage that just failed:
$ gcc -o prog main.o libx.a libyz.a -Wl,-trace-symbol=foo,-trace-symbol=bar
/usr/bin/ld: main.o: reference to foo
/usr/bin/ld: main.o: reference to bar
/usr/bin/ld: libx.a(p.o): definition of foo
/usr/bin/ld: libyz.a(qr.o): definition of bar
This time, no error. The definition of foo from libx.a(p.o) is
linked. The weak definition from libyz.a(qr.o) is ignored. The program
runs like:
$ ./prog
foo from p.c
bar from qr.c
If a symbol definition isn't weak, it is strong. The linker's rules are:
At most one strong definition of a symbol can be linked.
If one or more weak definitions, as well as a strong definition, are input,
then the one strong definition is linked and the all the weak ones are ignored.
If only weak definitions are input, then the linker can pick any one of them
arbitrarily. (In practice, it picks whichever one if finds first).
Do not use weak symbol definitions simply to escape from multiple definition
errors that take you by surprise. Such surprises mean that you don't understand
your linkage. Analyse it and fix it so that you are no longer trying to make
a program containing multiple definitions of the same thing.
Weak symbol definitions are usually generated by your compiler, behind the
scenes, to implement features of the source language that require them ( e.g.
global inline function definitions, or template instantiations in C++).
Use them yourself only if you understand exactly why you want the linker to
input multiple definitions of the same symbol.
What happens is implementation specific (and could be not even specified in C11 standard n1570, but I leave you to check that; AFAIK that standard don't speak of libraries - just of translation units). I believe the scenario you gives is some undefined behavior, so you could be scared (since anything is allowed to happen). And it probably is implementation defined.
In practice, on my Linux system, I'll get some error at link time (at least for static libraries). Read the Program Library HowTo and the documentation of the ld linker. Be aware that the GCC compiler is (sometimes) running ld (with many extra options, which are usually hidden to you). So invoke gcc with the -v flag (to understand how ld is started by your gcc command).
If you link two shared libraries on Linux, it becomes more interesting. But read Drepper's How to Write Shared Libraries. IIRC, the first symbol definition overrides the second. For example, you could use jemalloc and link the -ljemalloc ahead of the implicit -lc (with both libraries defining a malloc symbol). Be also aware of plugins and of the dynamic linker (on Linux, see dlopen(3) & dlsym(3) & ld-linux.so(8)).
Linux also has weak symbols, see this, and its GCC has visibility attribute.
On Windows (which I don't know and never used) things could be different. However, you'll still be able some "multiply defined symbol" error at link time.
The linker works in an operating system specific way. So read Levine's Linkers and Loaders (which explains how both Windows and Unix linkers work, and the details are different). To learn more about OSes, read Operating Systems: Three Easy Pieces (freely downloadable).
In my makefile I have
readline: readline.h readline.c
gcc -c -o readline readline.c
car: car.c car.h readline.h
gcc -c -o car car.c
dealer.o: dealer.c car.h
gcc -c -o dealer dealer.c
dealer: car.o dealer.o readline.o
gcc car.o dealer.o readline.o
readline.h contains a function prototype that reads in strings that my professor gave us, readline.c is the function,car.c contains a struct with car information, and the various functions for operating on a linked list, dealer.c is where the main function is.
This is my first time with makefiles but I have been getting various errors that are hard to understand saying something about multiple definition of certain functions (some actually in my code and some I guess deep in my code for the system) I don't know why I'm getting these errors.
My goal is to make the main program by linking all the components together.
Errors:
gcc car.o dealer.o readline.o
dealer.o: In function `_start':
(.text+0x0): multiple definition of `_start'
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/crt1.o:(.text+0x0): first defined here
dealer.o: In function `printList':
(.text+0x4ee): multiple definition of `printList'
car.o:car.c:(.text+0x33a): first defined here
dealer.o: In function `_fini':
(.fini+0x0): multiple definition of `_fini'
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/crti.o:(.fini+0x0): first defined here
dealer.o:(.rodata+0x0): multiple definition of `_IO_stdin_used'
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/crt1.o:(.rodata.cst4+0x0): first defined here
dealer.o: In function `__data_start':
(.data+0x0): multiple definition of `__data_start'
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/crt1.o:(.data+0x0): first defined here
dealer.o:(.rodata+0x8): multiple definition of `__dso_handle'
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/crtbegin.o:(.rodata+0x0): first defined here
dealer.o: In function `clearList':
(.text+0x5e2): multiple definition of `clearList'
car.o:car.c:(.text+0x42e): first defined here
dealer.o: In function `append_to_list':
(.text+0x1b4): multiple definition of `append_to_list'
car.o:car.c:(.text+0x0): first defined here
dealer.o: In function `find_car':
(.text+0x3db): multiple definition of `find_car'
car.o:car.c:(.text+0x227): first defined here
dealer.o: In function `_init':
(.init+0x0): multiple definition of `_init'
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/crti.o:(.init+0x0): first defined here
readline.o: In function `readLine':
readline.c:(.text+0x0): multiple definition of `readLine'
dealer.o:(.text+0x620): first defined here
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/crtend.o:(.dtors+0x0): multiple definition of `__DTOR_END__'
dealer.o:(.dtors+0x8): first defined here
/usr/bin/ld: error in dealer.o(.eh_frame); no .eh_frame_hdr table will be created.
collect2: ld returned 1 exit status
make: *** [dealer] Error 1
I understand what makefiles are for and what they are suppose to do but I cant seem to get this working.
Your makefile makes no sense.
readline: readline.h readline.c
gcc -c -o readline readline.c
So your target is "readline", but you use -c, so really it is just "readline.o" - very non standard naming convention. Specifically designed to confuse? This will produce an object file (not an exe) called "readline"
car: car.c car.h readline.h
gcc -c -o car car.c
Same as "readline". This will produce an object file (not an exe) called "car"
dealer.o: dealer.c car.h
gcc -c -o dealer dealer.c
Not even close: the gcc is creating and object file (not an exe) called "dealer" but the target is "dealer.o". At least this time the -c is used properly - you are trying to make a ".o", it's just that the -o is wrong. Since the target is dealer.o (which is not produced) this will always run trying in vain to make dealer.o
dealer: car.o dealer.o readline.o
gcc car.o dealer.o readline.o
No -o, so you don't create "dealer", you create "a.out". Nothing even builds car.o, dealer.o or readline.o and so it will never create anything useful. At least there is no -c so this is perhaps closer to correct...
A friend of mine looked over my code and gave some suggestions for improvements. These suggestions should work, and we've ironed out all the bugs in the code itself, but upon trying to compile even a basic int main(), it throws up a bunch of errors regarding something in its own libraries. The only thing that changed is we refined the code down so that there were less repeated statements and also used booleans instead of other stuff.
Here's the code right now: http://pastebin.com/nG0Dr4h0
Here are the errors:
E:\Utils\compile\files>gcc -Werror -Wall leapYear.c leapYear.exe
leapYear.exe:crt1.c:(.text+0x280): multiple definition of `mainCRTStartup'
e:/utils/compile/c/gcc/bin/../lib/gcc/mingw32/4.7.1/../../../crt2.o:crt1.c:(.text+0x280): first defined here
leapYear.exe:crt1.c:(.text+0x2a0): multiple definition of `WinMainCRTStartup'
e:/utils/compile/c/gcc/bin/../lib/gcc/mingw32/4.7.1/../../../crt2.o:crt1.c:(.text+0x2a0): first defined here
leapYear.exe:crt1.c:(.text+0x2c0): multiple definition of `atexit'
e:/utils/compile/c/gcc/bin/../lib/gcc/mingw32/4.7.1/../../../crt2.o:crt1.c:(.text+0x2c0): first defined here
leapYear.exe:crt1.c:(.text+0x2d0): multiple definition of `_onexit'
e:/utils/compile/c/gcc/bin/../lib/gcc/mingw32/4.7.1/../../../crt2.o:crt1.c:(.text+0x2d0): first defined here
leapYear.exe:cygming-crtbegin.c:(.text+0x2e0): multiple definition of `__gcc_register_frame'
e:/utils/compile/c/gcc/bin/../lib/gcc/mingw32/4.7.1/crtbegin.o:cygming-crtbegin.c:(.text+0x0): first defined here
leapYear.exe:cygming-crtbegin.c:(.text+0x32c): multiple definition of `__gcc_deregister_frame'
e:/utils/compile/c/gcc/bin/../lib/gcc/mingw32/4.7.1/crtbegin.o:cygming-crtbegin.c:(.text+0x4c): first defined here
leapYear.exe:leapYear.c:(.text+0x334): multiple definition of `main'
C:\Users\[REDACTED]\AppData\Local\Temp\ccKNWKLb.o:leapYear.c:(.text+0x72): first defined here
leapYear.exe:crt1.c:(.bss+0x4): multiple definition of `_argc'
e:/utils/compile/c/gcc/bin/../lib/gcc/mingw32/4.7.1/../../../crt2.o:crt1.c:(.bss+0x4): first defined here
leapYear.exe:crt1.c:(.bss+0x0): multiple definition of `_argv'
e:/utils/compile/c/gcc/bin/../lib/gcc/mingw32/4.7.1/../../../crt2.o:crt1.c:(.bss+0x0): first defined here
e:/utils/compile/c/gcc/bin/../lib/gcc/mingw32/4.7.1/crtbegin.o:cygming-crtbegin.c:(.text+0x45): undefined reference to `_Jv_RegisterClasses'
collect2.exe: error: ld returned 1 exit status
You are asking gcc to compile two sources, one of which is an exe (already compiled item). As such, it detect a lot of duplication, as the exe already contains much of what it should link into the intermediary objects.
Change the invocation to
E:\Utils\compile\files>gcc -Werror -Wall leapYear.c -o leapYear.exe
To tell GCC that the output file is the exe, which will take it off of the input sources. Then it won't be trying to add in call implementations to a set of inputs that already has the implementations.
Add -c to the input source file. We get this error when -c option is not used to compiler flags. Like this-
gcc -Werror -Wall -c leapYear.c leapYear.exe
or
gcc -c leapYear.c -Werror -Wall leapYear.exe
I have read the other answers on this topic, and unfortunately they have not helped me. I am attempting to link several c programs together, and I am getting an error in response:
$ gcc -o runexp.o scd.o data_proc.o -lm -fopenmp
/usr/lib/gcc/x86_64-linux-gnu/4.6/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
make: * [runexp] Error 1
I have exactly one main function and it is in runexp. The form is
int main(void) {
...;
return 0;
}
Any thoughts on why I might get this error? Thanks!
You should provide output file name after -o option. In your case runexp.o is treated as output file name, not input object file and thus your main function is undefined.
You're not including the C file that contains main() when compiling, so the linker isn't seeing it.
You need to add it:
$ gcc -o runexp runexp.c scd.o data_proc.o -lm -fopenmp
You are overwriting your object file runexp.o by running this command :
gcc -o runexp.o scd.o data_proc.o -lm -fopenmp
In fact, the -o is for the output file.
You need to run :
gcc -o runexp.out runexp.o scd.o data_proc.o -lm -fopenmp
runexp.out will be you binary file.
Generally you compile most .c files in the following way:
gcc foo.c -o foo. It might vary depending on what #includes you used or if you have any external .h files. Generally, when you have a C file, it looks somewhat like the following:
#include <stdio.h>
/* any other includes, prototypes, struct delcarations... */
int main(){
*/ code */
}
When I get an 'undefined reference to main', it usually means that I have a .c file that does not have int main() in the file. If you first learned java, this is an understandable manner of confusion since in Java, your code usually looks like the following:
//any import statements you have
public class Foo{
int main(){}
}
I would advise looking to see if you have int main() at the top.
When I compile my code,I write gcc -g -Wall dene2 dene2.c in the console. Then gcc emits some text on the screen. I don't understand what this output means (I couldn't think of a meaningful title for that reason, sorry).
I have tried Google searching but haven't had any luck.
I'm not asking for a detailed examination of all of the output below. Just show me "how to catch fish".
dene2: In function `_start':
/build/buildd/eglibc-2.10.1/csu/../sysdeps/i386/elf/start.S:65: multiple
definition of `_start'
/usr/lib/gcc/i486-linux-gnu/4.4.1/../../../../lib/crt1.o:/build/buildd/eglibc-2.10.1
/csu/../sysdeps/i386/elf/start.S:65: first defined here
dene2:(.rodata+0x0): multiple definition of `_fp_hw'
/usr/lib/gcc/i486-linux-gnu/4.4.1/../../../../lib/crt1.o:(.rodata+0x0): first
defined here
dene2: In function `_fini':
(.fini+0x0): multiple definition of `_fini'
/usr/lib/gcc/i486-linux-gnu/4.4.1/../../../../lib/crti.o:(.fini+0x0): first defined
here
dene2:(.rodata+0x4): multiple definition of `_IO_stdin_used'
/usr/lib/gcc/i486-linux-gnu/4.4.1/../../../../lib/crt1.o:(.rodata.cst4+0x0): first
defined here
dene2: In function `__data_start':
(.data+0x0): multiple definition of `__data_start'
/usr/lib/gcc/i486-linux-gnu/4.4.1/../../../../lib/crt1.o:(.data+0x0): first defined
here
dene2: In function `__data_start':
(.data+0x4): multiple definition of `__dso_handle'
/usr/lib/gcc/i486-linux-gnu/4.4.1/crtbegin.o:(.data+0x0): first defined here
dene2: In function `_init':
(.init+0x0): multiple definition of `_init'
/usr/lib/gcc/i486-linux-gnu/4.4.1/../../../../lib/crti.o:(.init+0x0): first defined
here
/tmp/ccMlGkkV.o: In function `main':
/home/fatih/Desktop/dene2.c:5: multiple definition of `main'
dene2:(.text+0xb4): first defined here
/usr/lib/gcc/i486-linux-gnu/4.4.1/crtend.o:(.dtors+0x0): multiple definition of
`__DTOR_END__'
dene2:(.dtors+0x4): first defined here
collect2: ld returned 1 exit status
I think you probably want a -o in that command line:
gcc -g -Wall -o dene2 dene2.c
What you have there without the -o is trying to link dene2 with the result of compiling dene2.c. dene2 is probably left over in your directory from previous build attempt. That's why you're seeing all the duplicate symbol errors.
You are missing the -o in your compile line.
gcc -g -Wall -o dene2 dene2.c
The linker is trying to link your executable together with the source code you're current compiling, resulting in multiple definitions.