简体   繁体   English

使用内联函数乘法定义的链接器错误

[英]Multiply defined linker error using inlined functions

The linker is reporting multiply defined errors for an inline function. 链接器报告内联函数的乘法定义错误。

I have the following code in a header file: 我在头文件中有以下代码:

struct Port_Pin
{
    volatile uint32_t *     port_addr_set_value;    //!< Writing the pin value here sets the pin to high.
    volatile uint32_t *     port_addr_clr_value;    //!< Writing the pin value to this port clears the pin to low.
    volatile uint32_t *     port_addr_read_value;   //!< Address to read pin value.
    volatile uint32_t *     port_addr_enable;       //!< Writing the pin value here enables the pin (for reading or writing).
    volatile uint32_t *     port_addr_disable;      //!< Writing the pin value here disables the pin.
    volatile uint32_t *     port_addr_dir_output;   //!< Writing the pin value here sets the pin as an output.
    volatile uint32_t *     port_addr_dir_input;    //!< Writing the pin value here sets the pin as an input.
    unsigned int            pin_bit_position;       //!< Zero based, where position zero is first bit position.
};

inline void
Write_Port_Pin(const struct Port_Pin *  p_port,
               uint8_t                  bit)
{
    volatile uint32_t * port_addr = 0;
    port_addr = ((bit & 1) == 0) ? p_port->port_addr_clr_value
        : p_port->port_addr_set_value;
    *port_addr = 1 << p_port->pin_bit_position;
    return;
}

I include the header file in more than one source (.c) file. 我将头文件包含在多个源(.c)文件中。

I would like to have the above function pasted inline wherever it is called. 我想将上述函数内联粘贴到任何地方。
Is there a technique for this without have multiple definitions of the function in each source file that is included? 是否有一种技术可以在其中包含的每个源文件中对函数进行多个定义? If yes, please provide example. 如果是,请提供示例。

I need the performance optimization for an embedded platform. 我需要针对嵌入式平台的性能优化。
Are compilers or linkers smart enough to inline functions when they are defined in other translation units? 在其他翻译单元中定义编译器或链接器时,它们是否足够聪明以内联函数?

I am using Green Hills compiler, 4.2.4 on an embedded ARM9 platform. 我在嵌入式ARM9平台上使用4.2.4的Green Hills编译器。 Assume pre-2000 C language standard. 假定2000年以前的C语言标准。 This is C code not C++. 这是C代码而不是C ++。

inline is just a suggestion, not a command. 内联只是一个建议,而不是命令。 However, in general compilers are smart enough to do the right thing ( and Green Hills has a good reputation in so far as optimizations go ). 但是,总的来说,编译器足够聪明,可以做正确的事情(就优化而言,Green Hills享有很高的声誉)。

Make the function 'static inline', which will prevent the compiler from making the symbol exportable. 将函数设置为“静态内联”,这将阻止编译器使符号可导出。 That should fix your multiple definition link errors... the linker is complaining that the same function is exported from several source modules. 这应该可以解决您的多个定义链接错误...链接器抱怨从多个源模块中导出了相同的功能。

If you have inline definition in .h file and you include it in many .c files and try to compile a lib using armcc compiler. 如果您在.h文件中有内联定义,并且将其包含在许多.c文件中,请尝试使用armcc编译器来编译lib。 Now If you use --gnu compiler option to compile armcc code then also you see multiply define error while linking, because then compiler puts definition in each .c file and exports it. 现在,如果使用--gnu编译器选项来编译armcc代码,那么在链接时还会看到乘法定义错误,因为然后编译器会将定义放入每个.c文件中并导出。 It seems while trying to make your code GCC compatible, we get this drawback. 似乎在尝试使您的代码与GCC兼容时,我们遇到了这个缺点。

To avoid it, may be use --c99 option instead of --gnu. 为了避免这种情况,可以使用--c99选项代替--gnu。

and get rid of this multiply define issue in .c files due to inline functions export by compiler. 并摆脱了由于编译器导出的内联函数而导致的.c文件中的乘法定义问题。

Some important notes: 一些重要的注意事项:

It seems that you did not properly guard your header. 看来您没有适当地保护标题。

#ifndef NAME_H
#define NAME_H
//...contents go here...
#endif // NAME_H

This prevents multiple definitions when the header is #include d more than once. 当标头包含#include多次以上时,这可以防止多个定义。

It also seems like you think that you can force a compiler to inline your function. 似乎您还认为可以强制编译器内联函数。 This is not correct. 这是不正确的。 A crazy and obscure compiler flag aside, the compiler will always decide if it wants to inline your function in the produced code. 除了疯狂而晦涩的编译器标记外,编译器将始终决定是否要在生成的代码中内联函数。 The inline keyword has a different meaning/purpose than what you think, see here 内联关键字的含义/目的与您所想的不同,请参阅此处

It's not clear what you mean why "pre-2000 C language specification" - the last standard was finalised in 1999. Prior to that, inline wasn't a keyword at all. 目前尚不清楚您为什么要说“ 2000年前的C语言规范”(最后一个标准于1999年定稿)。在此之前, inline根本不是关键字。

The 1999 standard has this to say: 1999年的标准说:

If all of the file scope declarations for a function in a translation unit include the inline function specifier without extern , then the definition in that translation unit is an inline definition . 如果翻译单元中某个函数的所有文件范围声明都包含不带externinline函数说明符,则该翻译单元中的定义内联定义 An inline definition does not provide an external definition for the function, and does not forbid an external definition in another translation unit. 内联定义不为函数提供外部定义,也不禁止在另一个翻译单元中使用外部定义。 An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. 内联定义提供了外部定义的替代方法,翻译器可以使用该替代方法在同一翻译单元中实现对该函数的任何调用。 It is unspecified whether a call to the function uses the inline definition or the external definition. 未指定对函数的调用是使用内联定义还是使用外部定义。

This means that as long as you don't have a declaration of Write_Port_Pin() with the extern qualifier, the compiler shouldn't generate an external definition of the function, so it shouldn't bother the linker. 这意味着只要您没有使用extern限定符声明Write_Port_Pin() ,编译器就不会生成该函数的外部定义,因此它不会打扰链接程序。 I'd submit this as a bug to your compiler vendor if I were you. 如果是您,我会将其作为错误提交给您的编译器供应商。

In C you cannot define a function with the same name in multiple places whether it is inline or not. 在C语言中,无论是否内联,都无法在多个位置定义具有相同名称的函数。

The best way to handle this is to declare the function in a header (along with the structure definition it depends on, like so: 处理此问题的最佳方法是在标头中声明函数(及其依赖的结构定义,如下所示:

/* port_control.h */

struct Port_Pin              
{              
    volatile uint32_t *     port_addr_set_value;    //!< Writing the pin value here sets the pin to high.              
    volatile uint32_t *     port_addr_clr_value;    //!< Writing the pin value to this port clears the pin to low.              
    volatile uint32_t *     port_addr_read_value;   //!< Address to read pin value.              
    volatile uint32_t *     port_addr_enable;       //!< Writing the pin value here enables the pin (for reading or writing).              
    volatile uint32_t *     port_addr_disable;      //!< Writing the pin value here disables the pin.              
    volatile uint32_t *     port_addr_dir_output;   //!< Writing the pin value here sets the pin as an output.              
    volatile uint32_t *     port_addr_dir_input;    //!< Writing the pin value here sets the pin as an input.              
    unsigned int            pin_bit_position;       //!< Zero based, where position zero is first bit position.              
};              

/* Declare the function here so other modules know about it. */        
inline void              
Write_Port_Pin(const struct Port_Pin *  p_port,              
               uint8_t                  bit);

Then define the function in a .c source file in one place: 然后在一个地方的.c源文件中定义函数:

/* port_control.c */

#include "port_control.h"

inline void                     
Write_Port_Pin(const struct Port_Pin *  p_port,                     
               uint8_t                  bit)                     
{                     
    volatile uint32_t * port_addr = 0;                     
    port_addr = ((bit & 1) == 0) ? p_port->port_addr_clr_value                     
        : p_port->port_addr_set_value;                     
    *port_addr = 1 << p_port->pin_bit_position;                     
    return;                     
} 

Then #include this header file in all of the .c files that call the function. 然后在所有调用该函数的.c文件中#include此头文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 多重定义符号的链接器错误 - Linker error for multiply defined symbols 可以内联动态库中定义的小型函数吗? - Can small functions defined in dynamic libraries be inlined? 使用自定义共享库中定义的 function 时出现 Linker 错误 - Linker error when using a function defined in a custom shared library C链接器错误:。\\ _ build \\ ble_app_hids_keyboard.axf:错误:L6200E:符号UX_captureStarted已乘以定义(由sens.o和main.o定义) - C linker error : .\_build\ble_app_hids_keyboard.axf: Error: L6200E: Symbol UX_captureStarted multiply defined (by sens.o and main.o) 函数仅在标题中定义时才会内联。 我错过了什么吗? - Functions only getting inlined if defined in a header. Am I missing something? 瑞萨编译错误符号_FunctionName多次定义 - Renesas compilation error symbol _FunctionName multiply defined 链接器实际上对多重定义的“内联”函数做了什么? - What do linkers actually do with multiply-defined `inline` functions? 使用SDL库时的链接器错误:main.obj中已定义的_main - Linker Error when using the SDL Library: _main already defined in main.obj 在C中的内联函数中循环展开 - Loop unrolling in inlined functions in C C语言中的内联Setter和Getter函数 - Inlined Setter and Getter functions in C
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM