-1

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

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

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

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

以下是我遇到的错误类型,从第一个错误开始(我没有发布所有输出):

/code/libraries/libsolver.a(Solver1.o): In function _fileno(_IO_FILE*)': Solver1.cpp:(.text+0x0): multiple definition of_fileno(_IO_FILE*)' main.o:main.cpp:(.text+0x1bc0): 首先定义在这里

/code/libraries/libsolver.a(Solver2.o): In function _fileno(_IO_FILE*)': Solver2.cpp:(.text+0x0): multiple definition of_fileno(_IO_FILE*)' main.o:main.cpp:(.text+0x1bc0): 首先定义在这里

/code/libraries/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 

回复雅各布:输出:

“grep _fileno”/usr/include/* -R

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

/usr/include/dirent.h:#if (defined __USE_BSD || defined __USE_MISC) && !defined d_fileno /usr/include/dirent.h:#define d_ino d_fileno /* 向后兼容。*/ /usr/include/lcms.h:#define fileno _fileno /usr/include/libdwarf/libdwarf.h: Dwarf_Unsigned * /*ret_fileno*/, /usr/include/libio.h:#define _IO_DELETE_DONT_CLOSE 0x40 /* Don '不要在清理时调用 close(_fileno)。*/ /usr/include/libio.h: int _fileno; /usr/include/linux/coda.h: u_int32_t d_fileno; /* 入口文件数 */ /usr/include/linux/mtio.h: __kernel_daddr_t mt_fileno; /* 磁带上当前文件的数量 */ /usr/include/sys/mtio.h: __daddr_t mt_fileno; /* 磁带上当前文件的数量。*/ /usr/include/X11/Xw32defs.h:#define fileno _fileno

编辑

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

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

这就是“固定”的东西(对不起,粗体,大文本;似乎无法关闭它):

定义 SOLVER_C_CONVERSION;

无效__cdecl;

万一

这是出现问题时的样子:

定义 SOLVER_C_CONVERSION 无效 __cdecl

万一

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

4

1 回答 1

2

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

跟踪包含依赖项

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

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

这将显示一个依赖树(自顶向下阅读)

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

最后你可以试着理解,为什么_fileno被定义了多次。

如果你想要一个更好的依赖输出,你通常可以尝试使用doxygen生成包含依赖。


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

-Wl,-z,multiple
于 2013-07-22T15:41:28.040 回答