Multiple definition of built-in functions when linking static libraries

I have a C ++ program that I am compiling with mingw (gcc for Windows). Using the TDM mingw release, which includes gcc 4.4.1. Executable links to two files of a static library (.a): On of them is a third-party library written in C; the other is the C ++ library I wrote, which uses the C library, provides my own C ++ API on top.

The function (in my opinion, excessive) of the C library functionality is implemented in built-in functions. You cannot avoid enabling built-in functions when using the C API library, but when I try to link all this together, I get link errors saying that there are many definitions of all built-in functions - both of them I have called in my C cover library ++ and those that I donโ€™t have, basically something that was defined inline in the headers, got a function created for it in both the C library and the C ++ library.

It does not cause multiple detection errors when the included files are used several times in different .c or .cpp files in the same project; the problem is that it generates one definition for each library.

How / why does the compiler generate functions and symbols for these built-in functions in both libraries? How can I make it stop generating them in my code? Is there a tool that I can run to remove duplicate functions from a .a file or a way to make the linker ignore multiple definitions?

(FYI, a third-party library includes #ifdef __cplusplus and extern "C" guards in all its headers, anyway, if this were a problem, it would not cause a multiple definition of the character, it would cause the opposite problem, because the character would be undefined or at least different.)

It is noteworthy that link errors do not occur if I refer to a third party DL library; however, then I get strange runtime errors that seem to be related to my code having its own version of the functions that it should call from the DLL. (As if the compiler were creating local versions of functions that I hadnโ€™t requested.)

Similar versions of this question were asked earlier, but I did not find an answer to my situation in any of them:

The answer to this question was that the poster was a significant determinant, my problem was the multiple definition of built-in functions: Repeated multiple definition errors from including the same header in several cpps

It was an MSVC program, but I use mingw; Also, the problem with the posters in this question was defining the C ++ class constructor outside the class body in the header, while my problem was with the built-in C: Static Lib Multiple Definition Functions

This fool renamed all his C-code as files in C ++, and his C code was not C ++ - safe: Multiple definition of a set of std :: functions when binding

This one just wanted to know why a violation of the definition rule was not a mistake: the unpredictable behavior of Inline functions with different definitions

+10
c ++ c inline-functions linker-errors
Feb 07 '10 at 17:47
source share
1 answer

First you need to understand the built-in C99 model - maybe something is wrong with your headers. There are two types of definitions for built-in functions with external (non-static) binding

  • External definition
    This definition of a function can appear only once in the entire program in the designated TU. It provides an exported function that can be used from other TUs.

  • Inline definition
    They appear in each TU, which is declared as a separate definition. Definitions do not have to be identical to each other or to an external definition. If they are used inside the library, they can omit the verification of function arguments that would otherwise be executed in the external definition.

Each function definition has its own local static variables, because their local declarations have no relationship (they are not shared, as in C ++). A definition of a non-static built-in function will be a built-in definition if

  • Each function declaration in TU includes an inline specifier and
  • A function declaration in TU does not include an extern specifier.

Otherwise, the definition that should appear in this TU (since the built-in functions must be defined in the same TU where it is declared) is an external definition. When calling the built-in function, it did not indicate whether an external or built-in definition was used. However, since the function defined in all cases still remains unchanged (since it has an external connection), its address is compared in all cases the same way, regardless of how many built-in definitions appear. Therefore, if you take the address of the function, the compiler will probably allow an external definition (especially if optimization is disabled).

An example that demonstrates the misuse of inline because it includes an external function definition twice in two TUs, resulting in a multiple definition error

 // included into two TUs void f(void); // no inline specifier inline void f(void) { } 

The following program is dangerous because the compiler has the right to use an external definition, but the program does not provide one

 // main.c, only TU of the program inline void g(void) { printf("inline definition\n"); } int main(void) { g(); // could use external definition! } 

I did some test cases using GCC, which further demonstrate the mechanism:

main.c

 #include <stdio.h> inline void f(void); // inline definition of 'f' inline void f(void) { printf("inline def main.c\n"); } // defined in TU of second inline definition void g(void); // defined in TU of external definition void h(void); int main(void) { // unspecified whether external definition is used! f(); g(); h(); // will probably use external definition. But since we won't compare // the address taken, the compiler can still use the inline definition. // To prevent it, i tried and succeeded using "volatile". void (*volatile fp)() = &f; fp(); return 0; } 

main1.c

 #include <stdio.h> inline void f(void); // inline definition of 'f' inline void f(void) { printf("inline def main1.c\n"); } void g(void) { f(); } 

main2.c

 #include <stdio.h> // external definition! extern inline void f(void); inline void f(void) { printf("external def\n"); } void h(void) { f(); // calls external def } 

Now the program displays what we expected!

 $ gcc -std=c99 -O2 main.c main1.c main2.c inline def main.c inline def main1.c external def external def 

Looking at the symbol table, we see that the symbol of the built-in definition is not exported (from main1.o ), but the external definition is exported (from main2.o ).




Now, if your static libraries have an external definition of their built-in functions (as it should be), they naturally conflict with each other. The solution is to make the built-in functions static or just rename them. They will always provide external definitions (therefore they are full definitions), but they are not exported because they have an internal relationship, therefore they do not conflict

 static inline void f(void) { printf("i'm unique in every TU\n"); } 
+12
Feb 07 '10 at 19:43
source share



All Articles