1

I have two libraries , named ( lib1 and lib2) , both are not dependent on each other. I do not have control over how these libraries are built. When I try to link them the order of linking dictates on different behaviors within the final executable,

For example:

If I link them as [1]

gcc $(CC_FLAGS) -o app.out -llib1 -llib2 

everything works fine

But, if I link them as following [2]

gcc $(CC_FLAGS) -o app.out -llib2 -llib1 

A segmentation fault occurs during executable run.

Any advice or pointer on the cause of this problem would be helpful.

Update:

Both of these libraries are dependent on another dynamic library, which is Apache Thrift ( Version 0.11.0) the segfault occurs on lib1 if it is compiled [1] option above, and exception occurs on lib2 if it compiled with option [2] above.

Update 2

The issue is due to global namespace violations between the libraries. Since thrift uses IDL mechanism to generate source files, Both libraries ( somehow ) defined the same namespace for their IDL definitions, hence such behavior was observed. Accepting the answer below as correct one since it addresses the question indirectly.

Thank you.

choppe
  • 493
  • 2
  • 11
  • 6
    The order of the libraries is important. https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html – Thomas Sablik Sep 23 '20 at 19:39
  • Does this answer your question? [Why does the order in which libraries are linked sometimes cause errors in GCC?](https://stackoverflow.com/questions/45135/why-does-the-order-in-which-libraries-are-linked-sometimes-cause-errors-in-gcc) – zgyarmati Sep 23 '20 at 19:41
  • @zgyarmati: Those answers explain why you might get a linker error, but I don't immediately see why you would get a crash at runtime. – Nate Eldredge Sep 23 '20 at 19:46
  • My bad, thx for clarifying. – zgyarmati Sep 23 '20 at 19:47
  • Have you tried investigating the segfault as you would any other? It could be a boring old memory error (buffer overrun etc) that just happens to be dependent on the precise layout of memory. – Nate Eldredge Sep 23 '20 at 19:47

1 Answers1

6

Is it possible that there resides a symbol (same name) in both of those libs?

Which one the linker will use to resolve an usage of such a symbol depends on the order (not sure where I've read this).

(HINT: This is just a guess)

So lets assume lib1 defines this function:

void foo( int, char* );

And lib2 defines:

void foo( int );

And somewhere we have a call like:

foo( 42 );

Now if the linker finds the definition of lib1, this foo most probably will get funny garbage as its 2nd argument.

Update (reaction to uptdate of question)

It is hard to make precise statements with the insight we have. So I can only point out some guesses and hope they'll help you. So sorry for my inaccuracy here. But I've no idea how else I could continue:

Guess 1:

Update says: "segfault occurs on lib1 if it is compiled [1] option above, and exception occurs on lib2 if it compiled with option [2]"

ABI incompatible exception handling in lib1? Something like this?

Guess 2 (Or should I name it "story"):

Our code inherits (and implements) an abstract class declared in thrift header. This impl then gets passed to lib1/lib2 (through our conflicting symbol) which perform calls to this impl. But lib1 used a different thrift header during compilation (or used conditional compiling, or used another version of thrift).

hiddenAlpha
  • 390
  • 4
  • 10
  • Verified that this could happen with dynamic libraries. – dbush Sep 23 '20 at 19:54
  • 1
    Good catch, in such case it is similar to `#define TRUE FALSE // Happy debugging bastards` :) – David Ranieri Sep 23 '20 at 19:59
  • 2
    @NateEldredge *both libraries are pulled in, and linking should fail with an error about the multiple definition.* Not with shared libraries, the linker will just note that the symbol exists as it checks the libraries in order. If you do an `ldd ...` on the resulting executable you'll see the order the shared objects are loaded in. In general, the first library loaded with a symbol that matches "wins". And the match is by symbol name **only** so `foo( int )` will match `foo( char * )` and even `foo( uint64_t *array )`. – Andrew Henle Sep 23 '20 at 20:05
  • Thanks for the catch, apparently both of these libraries are dependent on another dynamic library ( Apache thrift ) , The issue seems to be associated to thrift library loading. Have anyone else experienced this with apache thrift ? – choppe Sep 24 '20 at 13:05