Recently started C coding on Linux and ran into a 'multiple definition' error (sources A.c and B.c below)
gcc -Wall A.o B.o -o C
/usr/bin/ld: B.o: in function "Hello":
B.c:(.text 0x0): multiple definition of `Hello'; A.o:A.c:(.text 0x0): first defined here
Searching thru S.O, it was suggested to use this linker command line option
--allow-multiple-definition (-z muldefs)
Normally when a symbol is defined multiple times, the linker will report a fatal error.
These options allow multiple definitions and the first definition will be used.
Running this command bypassed the error message
gcc -Wall -Wl,--allow-multiple-definition A.o B.o -o C
It seemed peace was restored, however, it output
./C
Hello A
Hello A
World B
I was expecting this output below and "assumed" the linker would smoothly resolve any symbol conflicts, but at least keep the existing code functionality
Hello A
Hello B
World B
However, the resulting C ELF binary was modified as follows by examining the assembly output from objdump -S -M intel C
- Removed the duplicate Hello() in B.c
- Re-pointed any calls to Hello() in A.c
Questions
- Is renaming the symbol Hello() the only correct solution?
- Is it bad practice to use --allow-multiple-definition option?
- If possible, should the linker be more sentient about intended code functionality by restricting a functions visibility i.e., understand that Hello() is a duplicate symbol in B.o and calling it from World() should be confined to B.o instead of looking into A.o?
gcc -Wall -c A.c
#include <stdio.h>
void Hello(void)
{
printf("Hello A\n");
}
int main()
{
Hello();
World();
return 0;
}
gcc -Wall -c B.c
#include <stdio.h>
void Hello(void)
{
printf("Hello B\n");
}
void World(void)
{
Hello();
printf("World B\n");
}
EDITED
Based upon the comments/answers, adding the static keyword worked nicely
static void Hello(void)
{
printf("Hello B\n");
}
No need to use that command line option now
gcc -Wall A.o B.o -o C
Hello A
Hello B
World B
The real impetus for the question is that we build a UASM assembly object file, and given the tip about the C static keyword, at least I can now research what's available in UASM to make these functions PRIVATE to the object.
Thanks!
CodePudding user response:
Name change is best but you could also make them static (to limit access to the file they are in) or change the signature just a little bit.
Yes. Unbelievably bad ! In the real world you're expecting Hello() to do something, but now you're letting the compiler decide which version of Hello() to use - might be right. Might be wrong. It's madness to even have this option (IMHO).
You can do that by making them static.
This is all a bit academic. Why do you think having 2 global scope functions called Hello()
is a good idea in the first place ?