【问题标题】:Linker error not related to Linker [duplicate]链接器错误与链接器无关[重复]
【发布时间】:2018-06-22 16:06:28
【问题描述】:

我有一个非常具体的链接器错误案例:

'调用:GCC C++ 链接器 4 [arm-linux-gnueabihf]' arm-linux-gnueabihf-g++ -lpthread ./src/FPGA_Peripherals/AUX_IMU/AUX_IMU_functions.o
./src/main.o:在 功能主要': ../src/main.cpp:7: 未定义对 `function()'

的引用

为了这篇文章的目的,错误输出被截断。错误和函数定义所在的对象被突出显示。


代码使用 DS-5 C/C++ Eclipse 平台编译和链接,使用 GCC 4.x [arm-linux-gnueabihd](DS-5 内置)工具链:

  • GCC C++ 编译器 4 [arm-linux-gnueabihf]
  • GCC C 编译器 4 [arm-linux-gnueabihf]
  • GCC 汇编程序 4 [arm-linux-gnueabihf]
  • GCC C 链接器 4 [arm-linux-gnueabihf]
  • GCC C++ 链接器 4 [arm-linux-gnueabihf]
  • GCC 归档程序 4 [arm-linux-gnueabihf]

使用 Gnu Make Builder。


源代码结构在文件夹中:

  • src

    main.cpp

    • FPGA_外设

      • AUX_IMU

      header.h

      AUX_IMU_functions.c


产生错误的简约代码:

ma​​in.cpp

#include "header.h"

int main() {
    function();
    return 0;
}

header.h

void function(void);

AUX_IMU_functions.c

#include "header.h" 

void function(void){
    int i = 3;
};

使用 GCC C Compiler 4 [arm-linux-gnueabihf] 正确编译了 C 代码。 使用 GCC C++ Linker 4 [arm-linux-gnueabihf] 正确编译了 C++ 代码(本示例中未包含的其他文件)。


这显然不是与链接器相关的问题,但是如果链接器仍然产生此错误,还要检查什么?


一旦我将文件重命名为 .hpp 和 .cpp,错误就会消失。这是为什么 ? GCC C 和 GCC C++ 会产生不兼容的 .o 对象吗?

【问题讨论】:

  • 请注意,void function(void){ int i = 3; }; 中的最后一个分号是多余的。几乎,但不是完全无害;在严格的编译器选项下,您会收到有关空的全局声明的警告,这可能会让您感到困惑。初始化器和类型需要在右大括号后加分号;函数没有。
  • 您的错误是因为 C++ 类型安全链接破坏了函数名称。您需要告诉 C++ 编译器 function() 具有 C 链接:extern "C" void function(void);。你通常在函数声明之前使用#ifdef __cplusplus/extern "C"/#endif,或者在C函数声明块之前有条件地使用extern "C" {}
  • @JonathanLeffler 好吧,这是违反约束,所以允许编译失败。

标签: c++ c linker linker-errors


【解决方案1】:

您的错误是由于 C++ 类型安全链接造成的,该链接会破坏函数名称。您需要告诉 C++ 编译器 function() 具有 C 链接:

extern "C" void function(void);

但是,如果 C 和 C++ 编译器都应使用相同的头文件,则通常使用

#ifdef __cplusplus
extern "C"
#endif
void function(void);

对于单个函数声明,或使用

#ifdef __cplusplus
extern "C" {
#endif 

void function(void);
int  response(int arg);
…

#ifdef __cplusplus
}
#endif 

围绕具有 C 链接的函数的函数声明块。

您还可以在 C 中使用现有的标头,并在您的 C++ 代码中使用:

extern "C" {
#include "header.h"
}

【讨论】:

  • 谢谢。我之前实际上曾尝试使用 'extern "C" ',但它会产生其他错误,因为 GCC C 编译器无法识别它。现在我明白为什么添加#ifdef _cplusplus 如此重要
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-16
  • 1970-01-01
  • 2012-04-10
  • 2018-02-05
  • 2014-08-11
相关资源
最近更新 更多