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

StackOverflow https://stackoverflow.com/questions/17788165

Question

I am trying to compile a large C++ code (there are a few C files too) on a Linux cluster, having run it for some time on a Mac compiled with g++. On the cluster, I have to use either gcc/4.7.2 or intel/icpc (there is other software on the cluster that only works with those two compilers). I'm a newbie in dealing with compiling/linking problems, so no advice/tips is too simple.

I posted a question here a couple of days ago about a problem with using gcc/4.7.2. I haven't been able to resolve the problem, so now I'm trying icpc. Things have gone surprisingly well, but there is one problem I can't get past.

The problem is that I am getting errors related to "multiple definitions." These are associated with what seems to be a virtual function in a class that is inherited. I didn't write this code. There is a base class (Solver3), a derived class (Solver2), and another derived class (Solver1). The classes solve matrix equations. I can't tell which function is the problem because the error output is quite cryptic (see below; I have no function called "_fileno" and I can't find any generic definition of this term online). But the problem function is probably SolveWithSolver2 because it is the only function in the Solver1 class. I have no clue what could be wrong with it.

This is a bit over my head in terms of C++ knowledge and it is likely I'm making some beginner's mistake. For the past couple of days, I have used Google to search old forum posts. I have tried renaming what seems to be the problem function, I have tried inlining it. I get the same error. The code is very large and only a small part of it was written by me, so I can't post much of it. I will post what seems relevant and can add things if that would be helpful.

Here are the kinds of the errors I'm getting, starting from the first one (I have not posted all of the output):

/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): first defined here

/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): first defined here

/code/libraries/libsolver.a(Solver3.o): In function _fileno(_IO_FILE*)': Solver3.cpp:(.text+0x0): multiple definition of_fileno(_IO_FILE*)' main.o:main.cpp:(.text+0x1bc0): first defined here

... And so on

Here is the Solver1 header code:

#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

Here is the Solver2 header code:

#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 

Reply to Jakob: Output of:

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

/usr/include/bits/dirent.h:#define d_fileno d_ino /* Backwards compatibility. */ grep: warning: /usr/include/c++/4.3/x86_64-suse-linux/32: recursive directory loop

/usr/include/dirent.h:#if (defined __USE_BSD || defined __USE_MISC) && !defined d_fileno /usr/include/dirent.h:# define d_ino d_fileno /* Backward compatibility. */ /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't call close(_fileno) on cleanup. */ /usr/include/libio.h: int _fileno; /usr/include/linux/coda.h: u_int32_t d_fileno; /* file number of entry */ /usr/include/linux/mtio.h: __kernel_daddr_t mt_fileno; /* number of current file on tape */ /usr/include/sys/mtio.h: __daddr_t mt_fileno; /* Number of current file on tape. */ /usr/include/X11/Xw32defs.h:#define fileno _fileno

Edit:

Using Jakob's suggestion about compiler flags (adding -Wl and -z) to my OPTIONS, my error output became much more clear; I got file names, line numbers, and particular errors.

I have now dealt with the problem, in the sense that I can compile that library. But to be honest, I don't really know why the compiler complained to begin with or why my solution worked. The problem involved preprocessor directives, which I confess I know little about. If anyone cares to speculate on what the issue was, it would be interesting to know. I have never run into needing ";" in preprocessor directives before.

This is what "fixed" things (sorry about the bold, large text; can't seem to turn that off):

define SOLVER_C_CONVERSION;

void __cdecl;

endif

This is what it looked like when it was a problem:

define SOLVER_C_CONVERSION void __cdecl

endif

So now that I've fixed that problem, I have one more library to deal with. It is throwing up all kinds of errors that g++ previously ignored. I may bother you all once more later on today if I can't solve them. I'm pretty sure the problem is with my makefile.

Was it helpful?

Solution

To solve the problem with the multiple definitions, the first step would probably be

tracking down the include dependencies,

using the '-M' or the '-H' compiler flag, e.g. :

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

This will show you a dependency tree (read top-down )

Then you could figure out, which of the files defines the _fileno symbol.
(e.g by using the grep command)

and finally you could try to understand, why _fileno is defined multiple times.

If you want a nicer dependency output, you could in general try to generate the include dependencies with doxygen.


Alternatively as a workaround you could use following link flags which will prevent the compilation process from failing in case of multiple definitions:

-Wl,-z,multiple
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top