g++ undefined reference to typeinfo

Viewed 229648

I just ran across the following error (and found the solution online, but it's not present in Stack Overflow):

(.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?

(Bonus points if you can 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 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;

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

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

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

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.

Related