-1

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.

Ant
  • 753
  • 1
  • 9
  • 24
  • 1
    I'm not an expert with icc , but maybe the following link helps : [link](https://pm.bsc.es/projects/mcxx/ticket/574?version=7) – Jakob Kroeker Jul 22 '13 at 13:06
  • 1
    All this header code is utterly irrelevant. The error message names the offending symbol. Find it in the sources. That's the **only** thing that will help you. Preprocess the sources if all else fails. – n. m. could be an AI Jul 22 '13 at 13:08
  • What is contained in the _ErrorHandler.h_ , _helper.h_ and in the _Solver1.cpp_ ? – Jakob Kroeker Jul 22 '13 at 13:12
  • (Continued) The full set of sources includes your system headers, where this thing is likely to be found. – n. m. could be an AI Jul 22 '13 at 13:15
  • n.m, thanks for your reply. When you say that the error message names the offending symbol, where is that? I realize this is a dumb question, but I have never seen such error messages. – Ant Jul 22 '13 at 13:28
  • Jakob, thanks a lot... I took a look at your link and there's a suggestion to add "-Wl,-z" flags to my makefile. I just did that and recompiled. Now I'm getting error output that makes more sense. Now a particular file and line are identified. I'm getting error output like, "incomplete type is not allowed" and "variable "__cdexl" has already been defined." I'll follow those up. – Ant Jul 22 '13 at 13:35
  • You already know it's `_fileno`. Your own code may not mention it explicitly but this doesn't mean it's not there, thanks to the wonders of the preprocessor. – n. m. could be an AI Jul 22 '13 at 13:58
  • Thanks n.m. Now I understand you... Yes, I have looked high and low for what that means, and just can't figure it out. Those errors look totally cryptic to me. Luckily, Jakob suggested something that has created more understandable error output. – Ant Jul 22 '13 at 14:06
  • Remark: @Ant if I'm not wrong, the suggested linker flags only prevent the multiple definitions not to fail the build process. __fileno_ will still be multiple defined. If you grep for fileno `grep "_fileno" /usr/include/* -R` you will find the file where it is defined (replace '/usr/include' with the appropriate icc include path ) – Jakob Kroeker Jul 22 '13 at 14:34
  • Thanks a lot, Jakob. Yes, I am able to compile the libraries. When I try to run my code (that uses the libraries), then I get errors. But now that I have used your suggestion about the flags, I can see where the problem is! I can't fix it, but I know where it is and that's a major help. I have a file where there are lots of "#defines," like "#define SOMETHING solver_reset_something__" Then later in the file, there's "extern "C" {C_CALLCONV SOMETHING(void);"} For some reason, I'm getting errors associated with this. I'm trying to figure out why. – Ant Jul 22 '13 at 14:44
  • As far as your command suggestion, I will paste the output as an edit in my main post (I will work on figuring out what it means). – Ant Jul 22 '13 at 14:46
  • @Ant my command suggestion will not help you to solve the recent errors, it is only related to the `_fileno` multiple definition error . You could instead include the recent errors in your post in case you fail to resolve them by yourself after trying hard. (collegues and google are your friends) – Jakob Kroeker Jul 22 '13 at 15:02
  • Thanks Jakob. I am pretty sure that the multiple definition error is related to exactly what your flags revealed. Google is an old friend and I am using it right now to try and figure out what the problem is. I'll try to figure it out myself and will then update if I'm unsuccessful. These files are so long and complicated, that I'm not sure anyone could help right now! The basic issue is that I have many "ifdefs" in a particular file and later on they are used again. For some reason, the compiler does not like that. It has never been an issue with g++ before now. – Ant Jul 22 '13 at 15:05
  • 1
    @JakobKroeker: this `_fileno` has nothing to do with the error. It's an `int` field in the `FILE` structure. The multiply defined symbol is a C++ function. – n. m. could be an AI Jul 22 '13 at 19:47
  • 2
    @Ant: grepping the headers will probably give you nothing. There is more than one way to introduce an identifier by abusing the preprocessor. You need to preprocess the source files (run `gcc -E other-gcc-flags` on them) and look at the results. – n. m. could be an AI Jul 22 '13 at 19:52
  • @n.m you are absolutely right – Jakob Kroeker Jul 22 '13 at 20:50
  • Jakob and n.m., thanks a lot for your help. n.m., that's useful information that I will save for the future. Jakob's method did work to identify the problem files and lines (I have about 100 separate files, so was pretty lost before that). I solved the problem in the sense that I can now compile that library, but I'm not really sure why my solution worked or whether it is correct (I know little about the preprocessor directives). I'll add an edit to my question and if anyone has time to speculate, I'd be interested to know his/her thoughts. – Ant Jul 23 '13 at 05:42
  • 1
    @Ant, no your solution with void __cdecl is probably not correct; i recommend you to find out 1. how `#define` works by (reading and/or trying a small sandbox example) 2. find out what the effect of `__cdecl` is. – Jakob Kroeker Jul 24 '13 at 09:08
  • Jakob, thanks. You're right... It caused problems later on. I realized that the original was fine. I have worked through all my bugs and the entire code now compiles!! Thanks a lot for all your help!! – Ant Jul 24 '13 at 16:26

1 Answers1

2

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
Community
  • 1
  • 1
Jakob Kroeker
  • 333
  • 2
  • 15