MAGICS - undefined symbol: _ZTIN5eckit9ExceptionE
Question: I'm stuck on a runtime error "undefined symbol: _ZTIN5eckit9ExceptionE" like
this

    
    
    Start  2: basic_python
    2: Test command: /usr/local/Python/2.7.10/bin/python "coast.py"
    2: Environment variables:
    2:  PYTHONPATH=/opt/src/ecmwf/Magics-2.29.4-Source/build/python
    2:  LD_LIBRARY_PATH=/opt/src/ecmwf/Magics-2.29.4-Source/build/lib
    2:  MAGPLUS_HOME=/opt/src/ecmwf/Magics-2.29.4-Source/test/..
    2:  OMP_NUM_THREADS=1
    2: Test timeout computed to be: 1500
    2: Traceback (most recent call last):
    2:   File "coast.py", line 11, in <module>
    2:     from Magics.macro import *
    2:   File "/opt/src/ecmwf/Magics-2.29.4-Source/build/python/Magics/__init__.py", line 32, in <module>
    2:     _Magics = swig_import_helper()
    2:   File "/opt/src/ecmwf/Magics-2.29.4-Source/build/python/Magics/__init__.py", line 28, in swig_import_helper
    2:     _mod = imp.load_module('_Magics', fp, pathname, description)
    2: ImportError: /usr/local/Magics/2.29.4/gnu/4.4.7/lib/libMagPlus.so: undefined symbol: _ZTIN5eckit9ExceptionE
    

There was no error while building shared libaray libMagPlus.so. The error just
was raised at runtime when Python module loading it.

Checked with nm, the undefined symbol '_ZTIN5eckit9ExceptionE' is from a
static library libOdb.a, like this

    
    
    nm libOdb.a | grep _ZTIN5eckit9ExceptionE
                     U _ZTIN5eckit9ExceptionE
                     U _ZTIN5eckit9ExceptionE
                     U _ZTIN5eckit9ExceptionE
                     U _ZTIN5eckit9ExceptionE
                     U _ZTIN5eckit9ExceptionE
                     U _ZTIN5eckit9ExceptionE
    0000000000000000 V DW.ref._ZTIN5eckit9ExceptionE
                     U _ZTIN5eckit9ExceptionE
                     U _ZTIN5eckit9ExceptionE
                     U _ZTIN5eckit9ExceptionE
                     U _ZTIN5eckit9ExceptionE
                     U _ZTIN5eckit9ExceptionE
                     U _ZTIN5eckit9ExceptionE
    

But there was no any complaint about undefined symbol '_ZTIN5eckit9ExceptionE'
for the excutables which linked against the static library libOdb.a directly
at the both of complation time and runtime time. All C, Fortran codes also
worked well with the static library libOdb.a, except the shared library
libMagPlus.so.

The library LibMagPlus.so was linked like this

    
    
    /usr/bin/g++ -fPIC -pipe -O2 -g \
    -Wl,--disable-new-dtags -shared \
    -Wl,-soname,libMagPlus.so -o ../lib/libMagPlus.so \
    ... ...  \
    -Wl,-Bstatic -L$ODB_API/lib -lOdb \
    ... ...
    

The library libOdb.a was built like this

    
    
    usr/bin/ar qc ../../lib/libOdb.a  ... ...
    
    /usr/bin/ranlib ../../lib/libOdb.a
    

Searched the FAQ and Googled, little help with my problem. I knew little about
C++, and have no idea how to get this fixed.

[ In response to Jorge's inputs, updated these ]

Exceptions.h

    
    
    #ifndef eckit_Exceptions_h
    #define eckit_Exceptions_h
    
    #include <errno.h>
    
    #include "eckit/eckit.h"
    #include "eckit/eckit_version.h"
    
    #include "eckit/log/CodeLocation.h"
    #include "eckit/log/Log.h"
    #include "eckit/log/SavedStatus.h"
    #include "eckit/compat/StrStream.h"
    
    namespace eckit {
    
    //-----------------------------------------------------------------------------
    
    void handle_panic(const char*);
    void handle_panic(const char*, const CodeLocation&);
    
    /// @brief General purpose exception
    /// Derive other exceptions from this class and implement then in the class that throws them.
    class Exception : public std::exception {
    
    public: // methods
    
        /// Constructor with message
        Exception(const std::string& what, const CodeLocation& location = CodeLocation() );
    
        /// Destructor
        /// @throws nothing
        ~Exception() throw();
    
        virtual const char *what() const throw() {  return what_.c_str(); }
        virtual bool retryOnServer() const        { return false; }
        virtual bool retryOnClient() const        { return false; }
        virtual bool terminateApplication() const { return false; }
    
        static bool throwing();
        static void exceptionStack(std::ostream&,bool callStack = false);
    
        const std::string& callStack() const { return callStack_; }
    
    protected: // methods
    
    void reason(const std::string&);
    Exception();
    
        virtual void print(std::ostream&) const;
    
    private: // members
    
        std::string       what_;      ///< description
        std::string       callStack_; ///< call stack
        SavedStatus       save_;      ///< saved monitor status to recover after destruction
        Exception*        next_;
        CodeLocation      location_;  ///< where exception was first thrown
    
        friend std::ostream& operator<<(std::ostream& s,const Exception& p)
        {
            p.print(s);
            return s;
        }
    };
    

nm -Cl $ODB_API/lib/libOdb.a | grep -i "eckit::Exception"
    
    
                     U eckit::Exception::Exception(std::string const&, eckit::CodeLocation const&)  /opt/src/OdbAPI-0.10.2-Source/eckit/src/eckit/exception/Exceptions.h:84
                     U eckit::Exception::~Exception()       /opt/src/OdbAPI-0.10.2-Source/eckit/src/eckit/exception/Exceptions.h:108
    0000000000000000 W eckit::Exception::retryOnClient() const      /opt/src/OdbAPI-0.10.2-Source/eckit/src/eckit/exception/Exceptions.h:48
    0000000000000000 W eckit::Exception::retryOnServer() const      /opt/src/OdbAPI-0.10.2-Source/eckit/src/eckit/exception/Exceptions.h:47
    0000000000000000 W eckit::Exception::terminateApplication() const       /opt/src/OdbAPI-0.10.2-Source/eckit/src/eckit/exception/Exceptions.h:49
    0000000000000000 W eckit::Exception::what() const       /opt/src/OdbAPI-0.10.2-Source/eckit/src/eckit/exception/Exceptions.h:46
                     U eckit::Exception::print(std::ostream&) const
                     U typeinfo for eckit::Exception
    

I also tried to unpack all object files from libOdb.a and relink libMagPlus.so
with all of them with option '-fvisibility=default -rdynamic', like this

    
    
    ar x libOdb.a ( ./Odb ) 
    
    /usr/bin/g++ -fvisibility=default -rdynamic -fPIC -pipe -O2 -g \
    -Wl,--disable-new-dtags -shared \
    -Wl,-soname,libMagPlus.so -o ../lib/libMagPlus.so \
    ... ...  \
    ./Odb/*.o  \
    ... ...
    

But still got these undefined symbols

    
    
    U eckit::Exception::~Exception()       /opt/src/OdbAPI-0.10.2-Source/eckit/src/eckit/exception/Exceptions.h:108
    U eckit::Exception::print(std::ostream&) const
    U typeinfo for eckit::Exception
    

**Wondering if needs to touch Exceptions.h and how to touch it ?**

Anybody can help ?

Appreciating your time

Regards


Answer: Take a look at `Exceptions.h` file. Note how all your undefined symbols belong
to functions that are **declared but not defined**.

    
    
    ~Exception() throw();
    // [...]
    virtual void print(std::ostream&) const;
    

`eckit::Exception::~Exception()` is your destructor (declared in
`Exceptions.h:108` but not defined). The same applies to
`eckit::Exception::print(std::ostream&) const`.

In the case of `typeinfo for eckit::Exception`, the problem here is that you
have virtual functions that are not declared as _pure virtual_ (in abstract
classes), but are neither defined, so the type is not complete.

If I'm not wrong, as `eckit::Exception` class is meant to be superclass for
other derived classes, its destructor should be declared `virtual` too.

Check where are those missing functions declared. They should be either in an
object file skipped/missed by the archiver (if missing functions are defined
in a `.cpp` file) or in a header file that you didn't include (if they are
defined in a `.hpp` file).

See also: [g++ undefined reference to
typeinfo](http://stackoverflow.com/questions/307352/g-undefined-reference-to-
typeinfo)

