238
votes

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

17
I know it's an old post, but I had the same problem today, and the solution was simply to define my virtual function as virtual abc() {} in the base class, instead of virtual abc(); which gave the error.Nav
better yet as virtual void abc() =0; (if the base version is never called)dhardy
@Nav: If you define abc() like that you can easily forget to redefine abc() in the derived class and think that everything is okay, since you will still can call the function without any problem. A good practice for implementing pure virtual functions is found in this article, and this is to make the function print "Pure virtual function called" and then crash the program.HelloGoodbye
i was having same error. i've found that changing order of references to "lib" may help. i just moved problem lib's from the beggining to the end of the list and this resolved the problemOleg Vazhnev
GAH. This is now at least the second time I've navigated exactly to this page, to read the comment by @dhardy and say to myself 'Doh'. Just spent 45minutes trying to track down some crazy behavior and all I needed was = 0;.dwanderson

17 Answers

248
votes

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

160
votes

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]

65
votes

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;
29
votes

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.

24
votes

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

16
votes

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.

12
votes

I 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++.

10
votes

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.

6
votes

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.

6
votes

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

3
votes

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.

3
votes

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.

2
votes

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

2
votes

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.

1
votes

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.

1
votes

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.

0
votes

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