在 Linux 上编译C++代码。需要使用英特尔/ICPC 编译器。错误:"multiple definitions"与内部类相关

Compiling C++ code on Linux. Need to use intel/icpc compiler. Error: "multiple definitions" related to inerited class

本文关键字:multiple 错误 编译器 definitions 内部类 ICPC 英特尔 C++ 编译 Linux 代码      更新时间:2023-10-16

我正试图在Linux集群上编译一个大型C++代码(也有一些C文件),我已经在用g++编译的Mac上运行了一段时间。在集群上,我必须使用gcc/4.7.2或intel/icpc(集群上还有其他软件只能使用这两个编译器)。我是一个处理编译/链接问题的新手,所以没有什么建议/技巧太简单了。

几天前,我在这里发布了一个关于使用gcc/4.7.2的问题的问题。我还没能解决这个问题,所以现在我正在尝试icpc。事情进展得出奇地顺利,但有一个问题我无法克服。

问题是,我遇到了与"多个定义"相关的错误。这些错误与继承类中的虚拟函数有关。这个代码不是我写的。有一个基类(Solver3)、一个派生类(Solver2)和另一个派生类别(Solver1)。这些类求解矩阵方程。我不知道是哪个函数出了问题,因为错误输出非常神秘(见下文;我没有名为"_fileno"的函数,也找不到这个术语的任何通用定义)。但问题函数可能是SolveWithSolver2,因为它是Solver1类中唯一的函数。我不知道它可能出了什么问题。

就C++知识而言,这有点超出我的想象,很可能我犯了一些初学者的错误。在过去的几天里,我用谷歌搜索旧的论坛帖子。我试过重命名似乎有问题的函数,我试过内联它。我得到了同样的错误。代码很大,只有一小部分是我写的,所以我不能发布太多。我会发布看起来相关的内容,如果有帮助的话,我可以添加一些内容。

以下是我收到的各种错误,从第一个开始(我还没有发布所有的输出):

/code/librarys/libsolver.a(Solver1.o):In函数_fileno(_IO_FILE*)': Solver1.cpp:(.text+0x0): multiple definition of _fileno(_IO_FILE*)'main.o:main.cpp:(.text+0x1bc0):此处首次定义

/code/librarys/libsolver.a(Solver2.o):In函数_fileno(_IO_FILE*)': Solver2.cpp:(.text+0x0): multiple definition of _fileno(_IO_FILE*)'main.o:main.cpp:(.text+0x1bc0):此处首次定义

/code/librarys/libsolver.a(Solver3.o):在函数_fileno(_IO_FILE*)': Solver3.cpp:(.text+0x0): multiple definition of _fileno(_IO_FILE*)'中main.o:main.cpp:(.text+0x1bc0):此处首次定义

等等

这是Solver1头代码:

#ifndef SOLVER1
#define SOLVER1
#include "Solver2.h"
#include "ErrorHandler.h"
#ifdef SOLVER2
namespace code {
  class Solver1 : public Solver2 {
    public:
      Solver1( );
    //protected:
      virtual void SolveWithSolver2( Matrix& A,
                                     std::vector<double>& b,
                                     std::vector<double>& x,
                                     double tolerance );
    private:
      double pivot;
  };
} 
#endif
#endif

这是Solver2的标题代码:

#ifndef SOLVER2_H
#define SOLVER2_H
#include "Solver3.h"
#include "helper.h"
#ifdef SOLVER2
namespace code {
  class Solver2: public Solver3 {
    public:
      Solver2 ();
    //protected:
      virtual void SolveWithSolver2(Matrix& A,
                                     std::vector<double>& b,
                                     std::vector<double>& x,
                                     double tolerance) = 0;
    private:
      virtual void SolveEquation(Matrix& A,
                                       std::vector<double>& b,
                                       std::vector<double>& x,
                                       stl_index unknowns);
      double Residual(const Matrix& A,
                              const std::vector<double>& b,
                              std::vector< double >& x);
      double Calculate(const SparseMatrix& A,
                                  const std::vector<double >& b,
                                  const std::vector< double >& x);
      double residual;
  };
} 
#endif
#endif 

回复Jakob:输出:

"grep _fileno"/usr/include/*-R

/usr/include/bits/dirent.h:#define d_fileno d_ino/*向后兼容性。*/grep:警告:/usr/include/c++/4.3/x86_64-sus-linux/32:递归目录循环

/usr/include/dirent.h:#if(定义__USE_BSD||定义__USE_MISC)&amp;!defined d_fileno/usr/include/dirent.h:#define d_ino d_fileno/*向后兼容性。*//usr/include/lcms.h:#define fileno_文件号/usr/include/libdowar/libdowra.h:Dwarf_未签名*/*返回文件号*/,/usr/include/libio.h:#define _IO_DELETE_DONT_CLOSE0x40/*清理时不要调用close(_fileno)。*//usr/include/libio.h:int _fileno/usr/include/linux/coda.h:u_int32_t d_fileno/*条目的文件号*//usr/include/linux/mtio.h:__kernel_dddr_tmt_fileno;/*磁带上的当前文件数*//usr/include/sys/mtio.h:__daddr_t mt_fileno;/*电流数量文件在磁带上。*//usr/include/X11/Xw32defs.h:#define fileno _fileno

编辑

使用Jakob关于在OPTIONS中添加编译器标志(添加-Wl和-z)的建议,我的错误输出变得更加清晰;我得到了文件名、行号和特定的错误。

我现在已经处理了这个问题,因为我可以编译那个库。但老实说,我真的不知道为什么编译器一开始就抱怨,也不知道为什么我的解决方案有效。这个问题涉及到预处理器指令,我承认我对此知之甚少。如果有人想推测这个问题是什么,那就很有意思了。我以前从未在预处理器指令中遇到过需要";"的情况。

这就是"修复"的东西(对粗体、大文本感到抱歉;似乎无法关闭):

定义SOLVER_C_CONVERSION

无效__cdecl

endif

这就是它出现问题时的样子:

定义SOLVER_C_CONVERSION void __cdecl

endif

所以现在我已经解决了这个问题,我还有一个库要处理。它抛出了g++以前忽略的各种错误。如果我不能解决这些问题,今天晚些时候我可能会再次打扰大家。我确信问题出在我的makefile上。

要解决多个定义的问题,第一步可能是

跟踪include依赖项,

使用"-M"或"-H"编译器标志,例如:

gcc -H {use correct include flags here: -I$( include path)  } -c Solver1.cpp 

这将向您显示依赖关系树(自上而下读取)

然后,您可以弄清楚哪些文件定义了_fileno符号
(例如使用grep命令)

最后,您可以尝试理解为什么多次定义_fileno

如果您想要更好的依赖项输出,通常可以尝试使用doxygen生成include依赖项。


或者,作为一种变通方法,您可以使用以下链接标志,以防止在多个定义的情况下编译过程失败:

-Wl,-z,multiple