inline 函数 multiple define ERROR

转载 2015年11月19日 20:24:45


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

An (in my view, excessive) portion of the C library's functionality is implemented in inline functions. You can't avoid including the inline functions when you use the C library's API, but when I try to link it all together, I'm getting link errors saying there is a multiple definition of all of the inline functions - both ones I have called in my C++ wrapper library and ones which I have not, basically anything defined inline in the headers has gotten a function created for it in both the C library and the C++ library.

It doesn't cause multiple definition errors when the include files are used multiple times in different .c or .cpp files in the same project; the problem is just that it generates one definition per library.

How/why is the compiler generating functions and symbols for these inline functions in both libraries? How can I force it to stop generating them in my code? Is there a tool I can run to strip the duplicate functions from the .a file, or a way to make the linker ignore multiple definitions?

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

Notably, the link errors do NOT occur if I link to the third party C library's DLL; however then I get strange runtime failures that seem to have to do with my code having its own version of functions it should be calling from the DLL. (As if the compiler is creating local versions of functions I didn't ask for.)

Similar versions of this question have been asked before, however, I didn't find the answer to my situation in any of these:

The answer to this question was that the poster was multiply defining variables, my problem is multiple definition of inline functions: http://stackoverflow.com/questions/223771/repeated-multiple-definition-errors-from-including-same-header-in-multiple-cpps

This was an MSVC program, but I'm using mingw; also, the poster's problem in this question was the definition of a C++ class constructor outside of the class body in a header, while my problem is with C functions that are inline: http://stackoverflow.com/questions/717622/static-lib-multiple-definition-problem

This fool renamed all his C code as C++ files and his C code wasn't C++-safe:http://stackoverflow.com/questions/2208834/multiple-definition-of-lots-of-std-functions-when-linking

This one was just wanting to know why violating the one definition rule was not an error:http://stackoverflow.com/questions/2025380/unpredictable-behavior-of-inline-functions-with-different-definitions

shareimprove this question
 
1  
Notice that C99 inline semantics are different than the one of C++: In C, if one of the inline function declarations is explicitly specified extern, it creates an external definition - which is not an inline definition anymore. These external definitions cannot appear multiple times in the program. In C++ an explicit externon such a function has no effect. You are best off with doing static inline in C. – ᐅ Johannes Schaub - litb ᐊ Feb 7 '10 at 17:57
 
Normally inline function definitions are marked as 'weak' symbols and the linker is supposed to remove all duplicates itself. – Omnifarious Feb 7 '10 at 18:17
 
Thanks Johannes: using preprocessor definitions, the C library's header files declare these functions "inline" if in the C library's .c files, and "extern inline" when they're in my project. But I'm not sure why they did it that way. The C library does have some code that uses the address of a function as a unique key value. As a C++ programmer I view that as bad practice and I really pray they didn't use the address of an inline function that way. I feel there's almost enough information among these comments to put into an answer, although I still can't compile the program. – Dennis Feb 7 '10 at 19:48
 
If it uses the address of the function as a key somewhere and relies on the same address across TUs, you can't use static inline anymore. You could use -fgnu89-inline and use extern inline even in C mode, though (see gcc.gnu.org/onlinedocs/gcc/Inline.html . If you compile without -std=c99, it may even be the mode in effect anyway already, i think). – ᐅ Johannes Schaub - litb ᐊ Feb 7 '10 at 20:19
 
I added the "C" tag to this question and (because one cannot have 6 tag) removed the "multiple-definition-error", which seems to be covered by "linker-error" too. – ᐅ Johannes Schaub - litb ᐊ May 5 '12 at 15:22
up vote11down voteaccepted

First you have to understand the C99 inline model - perhaps there is something wrong with your headers. There are two kind of definitions for inline functions with external (non-static) linkage

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

  • Inline definition
    These appear in every TU where declared as a separate definition. The definitions do not need to be identical to one another or to the external definition. If used internal in a library, they can do omit checking on function arguments that would otherwise be done in the external definition.

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

  • Every function declaration in a TU includes the specifier inline, and
  • No function declaration in a TU includes the specifier extern.

Otherwise, the definition that must appear in that TU (because inline functions must be defined in the same TU where declared) is an external definition. In a call to an inline function it's unspecified whether the external or the inline definition is used. However, because the function defined in all cases is still the same (because it has external linkage), the address of it compares equal in all cases, no matter how many inline definitions appear. So if you take the function's address, it's likely the compiler resolves to the external definition (especially if optimizations are disabled).

An example that demonstrates a wrong use of inline, because it includes an external definition of a function twice in two TUs, causing 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 is free to use the 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 have made some test cases using GCC that demonstrate the mechanism further:

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 outputs 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 will see that the symbol of an inline definition is not exported (from main1.o), while an external definition is exported (from main2.o).


Now, if your static libraries each have an external definition of their inline functions (as they should), they will naturally conflict with each other. The solution is to make the inline functions static or just to rename them. These will always provide external definitions (so they are full fledged definitions), but they are not exported because they have internal linkage, thus not conflicting

static inline void f(void) {
  printf("i'm unique in every TU\n");
}
shareimprove this answer
 
 
This is a very good answer. Unfortunately, I still haven't been able to apply the knowledge to successfully compile my program - attempts to change the extern inlines to static inlines make it fail with the error that it is mixing static and nonstatic definitions of the same function. Perhaps I can use macros in my own code to change the names of the functions where I include the headers, but there are approximately 100 of these things in the headers... – Dennis Feb 7 '10 at 22:24
 
For further information, this discussion indicates the compiler optimization level can affect the issue:lkml.indiana.edu/hypermail/linux/kernel/0408.0/1787.html – Dennis Feb 7 '10 at 22:25
 
I found something similar when building with MinGW gcc, and discovered that the MinGW headers appear to be incompatible with the -std=gnu99 option. This caused a lot of multiply-defined symbols when I attempted to link, as definitions for the functions were placed in each object file built in this way. – David Gardner Mar 28 '12 at 16:02
 
...so I found that using -fgnu89-inline was a suitable workaround for our case, as we needed the gnu99 scoping on for-loop counter variables. (ugh) – David Gardner Mar 28 '12 at 16:03

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

An (in my view, excessive) portion of the C library's functionality is implemented in inline functions. You can't avoid including the inline functions when you use the C library's API, but when I try to link it all together, I'm getting link errors saying there is a multiple definition of all of the inline functions - both ones I have called in my C++ wrapper library and ones which I have not, basically anything defined inline in the headers has gotten a function created for it in both the C library and the C++ library.

It doesn't cause multiple definition errors when the include files are used multiple times in different .c or .cpp files in the same project; the problem is just that it generates one definition per library.

How/why is the compiler generating functions and symbols for these inline functions in both libraries? How can I force it to stop generating them in my code? Is there a tool I can run to strip the duplicate functions from the .a file, or a way to make the linker ignore multiple definitions?

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

Notably, the link errors do NOT occur if I link to the third party C library's DLL; however then I get strange runtime failures that seem to have to do with my code having its own version of functions it should be calling from the DLL. (As if the compiler is creating local versions of functions I didn't ask for.)

Similar versions of this question have been asked before, however, I didn't find the answer to my situation in any of these:

The answer to this question was that the poster was multiply defining variables, my problem is multiple definition of inline functions: http://stackoverflow.com/questions/223771/repeated-multiple-definition-errors-from-including-same-header-in-multiple-cpps

This was an MSVC program, but I'm using mingw; also, the poster's problem in this question was the definition of a C++ class constructor outside of the class body in a header, while my problem is with C functions that are inline: http://stackoverflow.com/questions/717622/static-lib-multiple-definition-problem

This fool renamed all his C code as C++ files and his C code wasn't C++-safe:http://stackoverflow.com/questions/2208834/multiple-definition-of-lots-of-std-functions-when-linking

This one was just wanting to know why violating the one definition rule was not an error:http://stackoverflow.com/questions/2025380/unpredictable-behavior-of-inline-functions-with-different-definitions

shareimprove this question
 
1  
Notice that C99 inline semantics are different than the one of C++: In C, if one of the inline function declarations is explicitly specified extern, it creates an external definition - which is not an inline definition anymore. These external definitions cannot appear multiple times in the program. In C++ an explicit externon such a function has no effect. You are best off with doing static inline in C. – ᐅ Johannes Schaub - litb ᐊ Feb 7 '10 at 17:57
    
Normally inline function definitions are marked as 'weak' symbols and the linker is supposed to remove all duplicates itself. – Omnifarious Feb 7 '10 at 18:17
    
Thanks Johannes: using preprocessor definitions, the C library's header files declare these functions "inline" if in the C library's .c files, and "extern inline" when they're in my project. But I'm not sure why they did it that way. The C library does have some code that uses the address of a function as a unique key value. As a C++ programmer I view that as bad practice and I really pray they didn't use the address of an inline function that way. I feel there's almost enough information among these comments to put into an answer, although I still can't compile the program. – Dennis Feb 7 '10 at 19:48
    
If it uses the address of the function as a key somewhere and relies on the same address across TUs, you can't use static inline anymore. You could use -fgnu89-inline and use extern inline even in C mode, though (see gcc.gnu.org/onlinedocs/gcc/Inline.html . If you compile without -std=c99, it may even be the mode in effect anyway already, i think). – ᐅ Johannes Schaub - litb ᐊ Feb 7 '10 at 20:19
    
I added the "C" tag to this question and (because one cannot have 6 tag) removed the "multiple-definition-error", which seems to be covered by "linker-error" too. – ᐅ Johannes Schaub - litb ᐊ May 5 '12 at 15:22
up vote11down voteaccepted

First you have to understand the C99 inline model - perhaps there is something wrong with your headers. There are two kind of definitions for inline functions with external (non-static) linkage

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

  • Inline definition
    These appear in every TU where declared as a separate definition. The definitions do not need to be identical to one another or to the external definition. If used internal in a library, they can do omit checking on function arguments that would otherwise be done in the external definition.

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

  • Every function declaration in a TU includes the specifier inline, and
  • No function declaration in a TU includes the specifier extern.

Otherwise, the definition that must appear in that TU (because inline functions must be defined in the same TU where declared) is an external definition. In a call to an inline function it's unspecified whether the external or the inline definition is used. However, because the function defined in all cases is still the same (because it has external linkage), the address of it compares equal in all cases, no matter how many inline definitions appear. So if you take the function's address, it's likely the compiler resolves to the external definition (especially if optimizations are disabled).

An example that demonstrates a wrong use of inline, because it includes an external definition of a function twice in two TUs, causing 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 is free to use the 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 have made some test cases using GCC that demonstrate the mechanism further:

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 outputs 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 will see that the symbol of an inline definition is not exported (from main1.o), while an external definition is exported (from main2.o).


Now, if your static libraries each have an external definition of their inline functions (as they should), they will naturally conflict with each other. The solution is to make the inline functions static or just to rename them. These will always provide external definitions (so they are full fledged definitions), but they are not exported because they have internal linkage, thus not conflicting

static inline void f(void) {
  printf("i'm unique in every TU\n");
}
shareimprove this answer
 
    
This is a very good answer. Unfortunately, I still haven't been able to apply the knowledge to successfully compile my program - attempts to change the extern inlines to static inlines make it fail with the error that it is mixing static and nonstatic definitions of the same function. Perhaps I can use macros in my own code to change the names of the functions where I include the headers, but there are approximately 100 of these things in the headers... – Dennis Feb 7 '10 at 22:24
    
For further information, this discussion indicates the compiler optimization level can affect the issue:lkml.indiana.edu/hypermail/linux/kernel/0408.0/1787.html – Dennis Feb 7 '10 at 22:25
    
I found something similar when building with MinGW gcc, and discovered that the MinGW headers appear to be incompatible with the -std=gnu99 option. This caused a lot of multiply-defined symbols when I attempted to link, as definitions for the functions were placed in each object file built in this way. – David Gardner Mar 28 '12 at 16:02
    
...so I found that using -fgnu89-inline was a suitable workaround for our case, as we needed the gnu99 scoping on for-loop counter variables. (ugh) – David Gardner Mar 28 '12 at 16:03

注意头文件规则,避免链接错误:重复定义(multiple defination)

注意头文件规则,避免链接错误:重复定义(multiple defination) - 作业部落  Cmd Markdown 编辑阅读器 https://zybuluo.com/uuprince/n...

multiple definition of 问题解决方法

问题描述: 在一个头文件a.h中定义一些变量x,在其他.c文件中(b.c,c.c)要用到。 用一般的全局变量的方法, 编译时总是提示error:multiple definition of x ...
  • wu070815
  • wu070815
  • 2013年04月10日 11:08
  • 22403

C语言里面的内联函数(inline)与宏定义(#define)探讨

C语言里面的内联函数(inline)与宏定义(#define)探讨   先简明扼要,说下关键: 1、内联函数在可读性方面与函数是相同的,而在编译时是将函数直接嵌入调用程序的主体,省去了调用/返回...

C语言中的内联函数(inline)与宏定义(#define)详细解析

C语言中的内联函数(inline)与宏定义(#define)详细解析 作者: 字体:[增加 减小] 类型:转载 内联函数与宏本质上是两个不同的概念如果程序编写者对于既要求快速,又要求可读的情况下...

C语言里面的内联函数(inline)与宏定义(#define)探讨

http://huxiongwei.spaces.eepw.com.cn/articles/article/item/85841 C语言里面的内联函数(inline)...

C语言里面的内联函数(inline)与宏定义(#define)探讨(转载)

先简明扼要,说下关键:1、内联函数在可读性方面与函数是相同的,而在编译时是将函数直接嵌入调用程序的主体,省去了调用/返回指令,这样在运行时速度更快。2、内联函数可以调试,而宏定义是不可以调试的。内联函...

#define和inline的区别 sizeof与strlen的区别 以及运算符函数关键字三种概念

以下内容为百度所找,经整理后发表 define函数定义一个常量,定义以后无法更改,常量值只能是字符串或者数字 无参宏定义的一般形式为:#define 标识符 字符串/数字 #define:是...
  • yoopbr
  • yoopbr
  • 2017年11月24日 18:59
  • 23

C语言里面的内联函数(inline)与宏定义(#define)探讨

C语言里面的内联函数(inline)与宏定义(#define)探讨 先简明扼要,说下关键: 1、内联函数在可读性方面与函数是相同的,而在编译时是将函数直接嵌入调用程序的主体,省去了调用/返回指...

const #define inline

  • 2012年04月12日 15:36
  • 27KB
  • 下载

解决Multiple dex files define Landroid/support/v4/accessibilityservice/AccessibilityServiceInfoCom

解决Multiple dex files define Landroid/support/v4/accessibilityservice/AccessibilityServiceInfoCom
  • jhope
  • jhope
  • 2016年10月25日 17:18
  • 401
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:inline 函数 multiple define ERROR
举报原因:
原因补充:

(最多只允许输入30个字)