tags:

views:

8258

answers:

5

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

+1  A: 

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;
cdleary
+15  A: 

This particular error is caused by 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).

paxdiablo
It is incorrect to say that `virtual void fn() = 0` is a definition. It is not a definition, but a mere *declaration*. The only reason the linker is not trying to resolve it is that the corresponding VMT entry will not refer to a function body (will contain null-pointer most likely). However, nobody prohibits you from calling this pure virtual function in a non-virtual manner, i.e. by using a fully-qualified name. In this case the linker *will* look for the body, and you will have to define the function. And yes, you *can* define a body for a pure virtual function.
AndreyT
+3  A: 

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

Tyler McHenry
Upmodded because I think this is more likely to be the cause of that specific error message (as opposed to the more general case of undefined methods...)
Alastair
One thing I had to get used to with SO is not referring to "above" answers since the order may change based on votes. I don't usually refer to any other answers now since they can be deleted as well. My belief is that answers should be standalone. I still refer to user names for attribution however.
paxdiablo
You can use typeid without a vtable; see my answer for the quotes from the gcc manual.
CesarB
+5  A: 

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.

CesarB
+2  A: 

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.

human