I just ran across the following error:
(.gnu.linkonce.[stuff]): undefined reference to [method] [object file]:(.gnu.linkonce.[stuff]): undefined reference to `typeinfo for [classname]'
Why might one get one of these "undefined reference to typeinfo" linker errors?
Can anyone explain what's going on behind the scenes?
18 Answers
One possible reason is because you are declaring a virtual function without defining it.
When you declare it without defining it in the same compilation unit, you're indicating that it's defined somewhere else - this means the linker phase will try to find it in one of the other compilation units (or libraries).
An example of defining the virtual function is:
virtual void fn() { /* insert code here */ }
In this case, you are attaching a definition to the declaration, which means the linker doesn't need to resolve it later.
The line
virtual void fn();
declares fn()
without defining it and will cause the error message you asked about.
It's very similar to the code:
extern int i; int *pi = &i;
which states that the integer i
is declared in another compilation unit which must be resolved at link time (otherwise pi
can't be set to it's address).
This can also happen when you mix -fno-rtti
and -frtti
code. Then you need to ensure that any class, which type_info
is accessed in the -frtti
code, have their key method compiled with -frtti
. Such access can happen when you create an object of the class, use dynamic_cast
etc.
[source]
10This occurs when declared (non-pure) virtual functions are missing bodies. In your class definition, something like:
virtual void foo();
Should be defined (inline or in a linked source file):
virtual void foo() {}
Or declared pure virtual:
virtual void foo() = 0;
0Quoting from the gcc manual:
For polymorphic classes (classes with virtual functions), the type_info object is written out along with the vtable [...] For all other types, we write out the type_info object when it is used: when applying `typeid' to an expression, throwing an object, or referring to a type in a catch clause or exception specification.
And a bit earlier on the same page:
If the class declares any non-inline, non-pure virtual functions, the first one is chosen as the “key method” for the class, and the vtable is only emitted in the translation unit where the key method is defined.
So, this error happens when the "key method" is missing its definition, as other answers already mentioned.
2If you're linking one .so to another, yet one more possibility is compiling with "-fvisibility=hidden" in gcc or g++. If both .so files were built with "-fvisibility=hidden" and the key method is not in the same .so as another of the virtual function's implementations, the latter won't see the vtable or typeinfo of the former. To the linker, this looks like an unimplemented virtual function (as in paxdiablo's and cdleary's answers).
In this case, you must make an exception for the visibility of the base class with
__attribute__ ((visibility("default")))
in the class declaration. For instance,
class __attribute__ ((visibility("default"))) boom{ virtual void stick(); }
Another solution, of course, is to not use "-fvisibility=hidden." That does complicate things for the compiler and linker, possibly to the detriment of code performance.
2The previous answers are correct, but this error can also be caused by attempting to use typeid on an object of a class that has no virtual functions. C++ RTTI requires a vtable, so classes that you wish to perform type identification on require at least one virtual function.
If you want type information to work on a class for which you don't really want any virtual functions, make the destructor virtual.
3I just spent a few hours on this error, and while the other answers here helped me understand what was going on, they did not fix my particular problem.
I am working on a project that compiles using both clang++
and g++
. I was having no linking issues using clang++
, but was getting the undefined reference to 'typeinfo for
error with g++
.
The important point: Linking order MATTERS with g++
. If you list the libraries you want to link in an order which is incorrect you can get the typeinfo
error.
See this SO question for more details on linking order with gcc
/g++
.
Possible solutions for code that deal with RTTI and non-RTTI libraries:
a) Recompile everything with either -frtti or -fno-rtti
b) If a) is not possible for you, try the following:
Assume libfoo is built without RTTI. Your code uses libfoo and compiles with RTTI. If you use a class (Foo) in libfoo that has virtuals, you're likely to run into a link-time error that says: missing typeinfo for class Foo.
Define another class (e.g. FooAdapter) that has no virtual and will forward calls to Foo that you use.
Compile FooAdapter in a small static library that doesn't use RTTI and only depends on libfoo symbols. Provide a header for it and use that instead in your code (which uses RTTI). Since FooAdapter has no virtual function it won't have any typeinfo and you'll be able to link your binary. If you use a lot of different classes from libfoo, this solution may not be convenient, but it's a start.
1In my case it was a virtual function in an interface class that wasn't defined as a pure virtual.
class IInterface { public: virtual void Foo() = 0; }
I forgot the = 0
bit.
In the base class (an abstract base class) you declare a virtual destructor and as you cannot declare a destructor as a pure virtual function, either you have to define it right here in the abstract class, just a dummy definition like virtual ~base() { } will do, or in any of the derived class.
If you fail to do this, you will end up in an "undefined symbol" at link time. Since VMT has an entry for all the pure virtual functions with a matching NULL as it updates the table depending on the implementation in the derived class. But for the non-pure but virtual functions, it needs the definition at the link time so that it can update the VMT table.
Use c++filt to demangle the symbol. Like $c++filt _ZTIN10storageapi8BaseHostE will output something like "typeinfo for storageapi::BaseHost".
Similarly to the RTTI, NO-RTTI discussion above, this problem can also occur if you use dynamic_cast and fail to include the object code containing the class implementation.
I ran into this problem building on Cygwin and then porting code to Linux. The make files, directory structure and even the gcc versions (4.8.2) were identical in both cases, but the code linked and operated correctly on Cygwin but failed to link on Linux. Red Hat Cygwin has apparently made compiler/linker modifications that avoid the object code linking requirement.
The Linux linker error message properly directed me to the dynamic_cast line, but earlier messages in this forum had me looking for missing function implementations rather than the actual problem: missing object code. My workaround was to substitute a virtual type function in the base and derived class, e.g. virtual int isSpecialType(), rather than use dynamic_cast. This technique avoids the requirement to link object implementation code just to get dynamic_cast to work properly.
I got a lot of these errors just now. What happened is that I split a header-file-only class into a header file and a cpp file. However, I didn't update my build system, so the cpp file didn't get compiled. Among simply having undefined references to the functions declared in the header but not implemented, I got a lot of these typeinfo errors.
The solution was to re-run the build system to compile and link the new cpp file.
in my case, i used a third-party library with header files and so file. i subclassed one class, and link error like this occurred when i try to instantiate my subclass.
as mentioned by @sergiy, knowning it could be the problem of 'rtti', i managed to workaround it by put the constructor implementation into separate .cpp file and apply '-fno-rtti' compile flags to the file. it works well.
as i am still not quite clear about the internal of this link error, i am not sure whether my solution is general. however, i think it worth a shot before trying the adaptor way as mentioned by @francois . and of course, if all source codes are available(not in my case), better do recompile with '-frtti' if possible.
one more thing, if you choose to try my solution, try make the separate file as simple as possible, and do not use some fancy features of C++. take special attention on boost related things, cause much of it depends on rtti.
I've got same error when my interface (with all pure virtual functions) needed one more function and I forgot to "null" it.
I had
class ICommProvider { public: /** * @brief If connection is established, it sends the message into the server. * @param[in] msg - message to be send * @return 0 if success, error otherwise */ virtual int vaSend(const std::string &msg) = 0; /** * @brief If connection is established, it is waiting will server response back. * @param[out] msg is the message received from server * @return 0 if success, error otherwise */ virtual int vaReceive(std::string &msg) = 0; virtual int vaSendRaw(const char *buff, int bufflen) = 0; virtual int vaReceiveRaw(char *buff, int bufflen) = 0; /** * @bief Closes current connection (if needed) after serving * @return 0 if success, error otherwise */ virtual int vaClose(); };
Last vaClose is not virtual so compiled did not know where to get implementation for it and thereby got confused. my message was:
...TCPClient.o:(.rodata+0x38): undefined reference to `typeinfo for ICommProvider'
Simple change from
virtual int vaClose();
to
virtual int vaClose() = 0;
fixed the problem. hope it helps
I encounter an situation that is rare, but this may help other friends in similar situation. I have to work on an older system with gcc 4.4.7. I have to compile code with c++11 or above support, so I build the latest version of gcc 5.3.0. When building my code and linking to the dependencies if the dependency is build with older compiler, then I got 'undefined reference to' error even though I clearly defined the linking path with -L/path/to/lib -llibname. Some packages such as boost and projects build with cmake usually has a tendency to use the older compiler, and they usually cause such problems. You have to go a long way to make sure they use the newer compiler.
With this error message, G++'s linker is telling you, that it cannot assemble the full static typeinfo descriptor for a given class, when it is needed. As many have already pointed out, this is most likely due to missing definitions of virtual functions.
The bad thing, though, is, that the order of error messages may be counter-intuitive, with the "undefined reference to typeinfo" occuring before the undefined references to the missing virtual definitions. Here an example, that I just experienced:
/usr/bin/ld: module.o:(.data.rel.ro+0x10): undefined reference to `typeinfo for type_xxx' /usr/bin/ld: module.o:(.data.rel.ro+0x28): undefined reference to `typeinfo for type_xxx' /usr/bin/ld: module.o:(.data.rel.ro+0x40): undefined reference to `typeinfo for type_xxx' /usr/bin/ld: module.o:(.data.rel.ro+0x150): undefined reference to `type_xxx::has_property(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
So that missing definition of type_xxx::has_property(const std::string&)
is only reported as the fourth error. So, sometimes it pays off to skip those error messages, that one doesn't understand, and handle the ones, first, that are easy to understand. Because in this case, adding the missing definitions then also fixes the problem with the undefined typeinfo references.
Check that your dependencies were compiled without -f-nortti
.
For some projects you have to set it explicitly, like in RocksDB:
USE_RTTI=1 make shared_lib -j4
In my case it is purely a library dependency issue even if I have dynamic_cast call. After adding enough dependency into makefile this problem was gone.
ncG1vNJzZmirpJawrLvVnqmfpJ%2Bse6S7zGiorp2jqbawutJoamlvY2p%2FcLOMrqWdnZaeu6awjKucn52imruksYytpmasqaWyqrrFqA%3D%3D