274

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?

vvvvv
  • 25,404
  • 19
  • 49
  • 81
cdleary
  • 69,512
  • 53
  • 163
  • 191
  • 51
    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 Nov 30 '10 at 09:04
  • 31
    better yet as `virtual void abc() =0;` (if the base version is never called) – dhardy Jul 09 '12 at 08:27
  • 3
    @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](http://www.artima.com/cppsource/pure_virtual.html), and this is to make the function print "Pure virtual function called" and then crash the program. – HelloGoodbye Sep 27 '12 at 11:44
  • 1
    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 problem – Oleg Vazhnev Sep 23 '14 at 10:02
  • 3
    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 Mar 09 '16 at 22:19
  • 1
    In my case, I changed the base destructor from = 0; to {};. Then it was fine. If you make a destructor virtual, you still have to define it in the base class. Because the derived class class destructor calls the base class destructor during destruction. It was unable to find the definition. – Raghav Navada Apr 10 '17 at 04:37

18 Answers18

281

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

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 34
    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. – AnT stands with Russia Jun 25 '10 at 00:41
  • 1
    And sometimes one even must declare a body for a pure virtual function. – mark Mar 25 '13 at 01:31
  • 3
    The compiler (g++) will tell you what is the missing symbol. Note: In case of dynamic library linking you may get a mangled name. Use c++filt to get it in a readable form. The typeinfo error with a class name was in my case because of a missing virtual destructor implementation in some base class. – chmike Jul 10 '13 at 14:24
  • 2
    The question specifically mentions that it is typeinfo that is missing, which has to do with rtti. See comment from Damon in http://stackoverflow.com/questions/11904519/c-what-are-the-causes-of-undefined-reference-to-typeinfo-for-class-name –  May 09 '14 at 22:38
  • 2
    I got this error because `-fno-rtti` was specified as a compiler option, not because a virtual function wasn't defined. I think it's a little misleading that the intro statement to this answer is "This particular error is caused by..." when it should rather be "One possible reason is because...". – gbmhunter Sep 11 '14 at 04:10
  • 1
    @gbmhunter, fair enough. Made the change. – paxdiablo Sep 11 '14 at 04:22
  • I was only able to solve this error, when I set the virtual void fun() = 0. I missed the =0. – nnrales Feb 06 '18 at 22:53
  • @paxdiablo - Perhaps it is a naive question, yet I was wondering: In Visual Studio (my case 15) this error does not rises (i.e.- the code compiles and runs correctly EVEN if I "`declare it without defining it in the same compilation unit`", meaning, the body of the virtual dtor is in the cpp file) - so, is it true to say that this is a "bug" in g++ (which does not happen in Visual Studio)? – Guy Avraham Oct 05 '18 at 08:09
  • In my case it was as simple as having forgotten the `= 0` after what I intended to be a pure virtual function definition (which is indeed interpreted by the compiler as "declaring a virtual function without defining it"). – PieterNuyts Dec 18 '19 at 16:14
185

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]

Sergiy Belozorov
  • 5,856
  • 7
  • 40
  • 73
  • 27
    THANK YOU SO MUCH. That fixed my problem after 5 hour searching. – steipete Jul 03 '11 at 13:05
  • 1
    source link is dead, it was surely the same as http://permalink.gmane.org/gmane.comp.gcc.help/32475 – math Apr 13 '12 at 10:10
  • 1
    Thanks for pointing this out. Original page is still available here: http://web.archive.org/web/20100503172629/http://www.pubbs.net/201004/gcc/25970-linker-error-undefined-reference-to-typeinfo-for-a-with-no-rtti-option.html – Sergiy Belozorov Apr 14 '12 at 07:04
  • 3
    StackOverflow.com to the rescue again! I wish I could upvote more than once. After banging my head on the keyboard for an hour your answer was what I needed. – spartygw Dec 02 '13 at 14:47
  • 2
    n+1 lives saved and still counting :) – Gabriel Feb 02 '16 at 15:14
  • pal, you saved me from one frustrating night. thanks a lot! in my case, i managed to workaround it by **just moving the constructor implementation of my subclass to a separate file and apply '-fno-rtti' flag to that file**. see my anwser for [details](http://stackoverflow.com/a/36326434/1994490) – uwydoc Mar 31 '16 at 07:14
  • I have the same issue, but the target which fails has NOTHING to do with the target I applied `-frtti` for. How do you explain that?? There is only 1 connection, that it is that a header file which uses dynamic_cast is within the same used library... – jaques-sam May 29 '19 at 13:50
  • Thanks. I got this error when one library was compiled with `fno-rtti` while another wasn't. Ensuring that all libraries were built with `fno-rtti` fixed the problem – mostafa.elhoushi Feb 07 '22 at 05:50
71

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
  • 69,512
  • 53
  • 163
  • 191
31

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
  • 43,947
  • 7
  • 63
  • 86
  • 3
    In my case, I had a base class which declared but did not define virtual methods that were not pure virtual. Once I made them pure virtual, which is what I meant, the linker errors went away. – Tatiana Racheva Jun 16 '11 at 18:42
  • @TatianaRacheva Thanks! The error reporting from the linker is less than helpful and for a large interface it's very easy to miss the lack of the '=0;' for pure virtual! – rholmes May 15 '15 at 19:11
27

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
  • 271
  • 3
  • 2
  • 2
    You don't need to export (unhide) the base class if it is abstract or unused, just the non-virtual functions, normally just the constructor. The *derived* classes on the other hand have to be exported, if they are used. – Chris Huang-Leaver Dec 20 '10 at 18:36
  • feels like a hack, but it did solve the symptoms on my side. Thanks ! – malat Jul 28 '14 at 07:19
18

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tyler McHenry
  • 74,820
  • 18
  • 121
  • 166
  • 2
    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 Nov 21 '08 at 01:20
  • 4
    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 Nov 21 '08 at 01:37
  • You can use typeid without a vtable; see my answer for the quotes from the gcc manual. – CesarB Nov 21 '08 at 01:37
16

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

Community
  • 1
  • 1
dinkelk
  • 2,676
  • 3
  • 26
  • 46
  • Thank you!!! I have spent over a day trying to find out why I was getting this error and nothing worked until I saw this reply and the one you linked to. Thanks so much!! – Irene Dec 30 '16 at 04:23
  • Actually linking order matters with ```clang``` as well, so this advice is universally applicable, thanks. – Fedor Jun 26 '21 at 13:37
  • Yes fixing the link order ultimately resolved this for me. The undefined reference to typeinfo error referred to a non-virtual class used within a linked class, with error of the form somelibrary.a (somefile.o):(.gcc_except_table+0x23c): undefined reference to `typeinfo for NS:CLASSNAME' In this case NS:CLASSNAME was implemented in a library otherlib.a which needed to be moved below somelibrary.a in the link order. I had several other library order related errors, but this was the only one that manifested itself with the typeinfo error. – Daemon42 Feb 09 '22 at 01:16
12

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Francois
  • 121
  • 1
  • 2
9

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.

Goosebumps
  • 919
  • 2
  • 14
  • 27
8

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

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Prashanth
  • 81
  • 1
  • 1
7

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.

FNE
  • 311
  • 2
  • 8
4

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.

Claudiu
  • 224,032
  • 165
  • 485
  • 680
4

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.

uwydoc
  • 83
  • 1
  • 1
  • 8
4

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

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.

Kemin Zhou
  • 6,264
  • 2
  • 48
  • 56
2

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.

Kai Petzke
  • 2,150
  • 21
  • 29
1

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
Vitaly Isaev
  • 5,392
  • 6
  • 45
  • 64
1

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.

jaques-sam
  • 2,578
  • 1
  • 26
  • 24
Charlie
  • 639
  • 9
  • 19