Search code examples
c++gccincludemultiple-definition-errorsymbolicc++

C++ multiple definition error when including external library


I'm trying to write a simple application allowing the user to perform a series of symbolic manipulations on a set of linear equations and am using the "Symbolicc++" library (more specifically, the latest version 3.35) for this purpose.

Since I don't have much experience with C++ and have never actually used a third-party library before, it's quite possible that I simply don't know how to properly use a library and am making some stupid mistake.

The problem is that I get a lot of multiple definition errors when I try to compile (and link) any program consisting of more than one file that includes the library's main header; the errors refer to functions and classes that are defined in the library's files (not mine).

A very simplistic example: suppose we have the files main.cpp, head.h and head.cpp. The contents is as follows:

main.cpp
------------------
#include <iostream>
#include "head.h"

int main()
{
    return 0;
}

head.h
------------------
#ifndef SOMETHING
#define SOMETHING

#include "symbolicc++.h"

#endif

head.cpp
------------------
#include "head.h"
//nothing

Of course, the files in the real program contain a lot more, but even with just this, trying to build the program with, e.g.:

g++ -I /path to library's header files/ main.cpp head.cpp

yields hundreds of error message along the likes of:

/tmp/ccYNzlEF.o: In function `Cloning::Cloning()':
head.cpp:(.text+0x0): multiple definition of `Cloning::Cloning()'
/tmp/ccNWUnnC.o:main.cpp:(.text+0x0): first defined here

where, e.g., Cloning::Cloning() is declared in cloning.h, which is one of the library's header files.

A program containing only a single file including symbolicc++.h works just fine.

I also tried building this project on Visual Studio 2012 and got a similar result.

Unfortunately, I wasn't able to find any information about this problem, as virtually all the materials I found concerned errors in header files created by the user (as opposed to libraries created by someone else), so any help would be appreciated.


Solution

  • This library seems seriously broken. The way it is designed, you cannot include "symbolicc++.h" multiple times without violating the one-definition rule.

    For example, let's have a look at cloning.h. It defines a Cloning class with a default constructor declaration:

    class Cloning
    {
     private: int refcount;
              void (*free_p)(Cloning*);
    // ...    
     public:  Cloning();
    // ...
    };
    

    Later on, within the header file, it also defines that constructor:

    Cloning::Cloning() : refcount(0), free_p(0) {}
    

    That's it. Every one of your *.cpp files which directly or indirectly includes cloning.h will be exposed to the definition of the same function. The linker notices the multiple definitions and gives up.

    Try to modify cloning.h. Remove the constructor definition line above and place the constructor definition into the class definition, making it an inline function:

    // just to see what's going on...
    class Cloning
    {
     private: int refcount;
              void (*free_p)(Cloning*);
    // ...
    
     public:  Cloning() : refcount(0), free_p(0) {};
    // ...
    };
    

    This will fix the error for Cloning::Cloning. But that's just to shed more light on the issue; I don't advise you to do this. It would be the library authors' job to fix their code.

    Further recommended reading: Why include guards do not prevent multiple function definitions?


    Here is a way for you to reproduce the same problem with a few lines of your own code:

    head.h:

    #ifndef SOMETHING
    #define SOMETHING
    
    struct Example
    {
        Example(); // constructor declaration
    };
    
    Example::Example() // constructor definition
    {
    }
    
    #endif
    

    head.cpp:

    #include "head.h"
    //nothing
    

    main.cpp:

    #include "head.h"
    
    int main()
    {
    }
    

    Example linker error (taken from Visual C++ 2013):

    1>main.obj : error LNK2005: "public: __thiscall Example::Example(void)" (??0Example@@QAE@XZ) already defined in head.obj
    1>[...] fatal error LNK1169: one or more multiply defined symbols found
    

    If you absolutely must use this library, you'll have to build your own safe wrapper around it. But frankly, just don't. I'm sure there are numerous other libraries that solve the same problems and that can actually be used according to C++ language rules and conventions.