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
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