Home > database >  Multiple definition errors during gcc linking in Linux
Multiple definition errors during gcc linking in Linux

Time:09-26

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

  1. Is renaming the symbol Hello() the only correct solution?
  2. Is it bad practice to use --allow-multiple-definition option?
  3. 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:

  1. 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.

  2. 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).

  3. 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 ?

  • Related