2

The problem I have is very similar to the one discussed here: g++ undefined reference to typeinfo

Even so, I believe I so not have the same issue, and the answers to that topi do not really help me. What i have is :

class Base
{
    virtual ~Base() {}
    virtual void foo() = 0;
    // some other pure virtual behaviors
};

class Derived : public Base
{
    void foo() {/* do stuff */}
    // override for all other virtual behaviors
};

then in different functions I have :

void bar( Base * base )
{
    Derived * derived = dynamic_cast<Derived *>(base);
}

void foobar( const Base & base1, const Base & base2 )
{
    if ( typeid(base1) == typeid(base2) )
        /* do something */;
}

So I'm sure the function is either pure virtual or defined (even though the object can never be Base). This should not give any problems, and it is different from the quoted discussion because i'm sure i override the virtual function. Even so, when compiling with clang++, it issues an unresolved external for both typeid and dynamic_cast when used on Derived, while it doesn't do so for other classes that inherit from Base, and override the same foo behaviors. Why does it do so?

here the errors:

error LNK2019: unresolved external symbol __imp___RTDynamicCast
error LNK2019: unresolved external symbol __imp___RTtypeid

Am i just missing something silly, or misinterpreting these errors?

Edit

I realized the code examples I first gave were not descriptive enough :

class Base
{
public:
    virtual ~Base() {}
};

class Interface : public Base
{
public:
    virtual void foo() = 0;
    // some other pure virtual behaviors
};

class Derived : public Interface
{
public:
    void foo() {/* do stuff */}
    // override for all other virtual behaviors
};

and

void bar()
{
    Base * base = new Derived;
    Interface * interface = dynamic_cast<Interface *>(base);
    interface->foo()
}

fit better to what i'm trying to do.

  • If you are using C++11 or newer, you can use the keyword [`override`](http://en.cppreference.com/w/cpp/language/override) in the declaration of the overriding function. This insures that you have not missed some detail in the functions prototype. It would look like this: `void foo() override {...}`. – JojOatXGME Oct 25 '17 at 21:40
  • In visual studio compiles and works just fine. – Massimo Castrioto Oct 25 '17 at 21:41
  • you simply need add lib file where this symbols defined. for example `msvcurt.lib` – RbMm Oct 25 '17 at 21:42
  • @JojOatXGME thanks for the tip, but I already knew that. Unfortunately I cannot use c++11 in this project. – Massimo Castrioto Oct 25 '17 at 21:43
  • you yourself use `typeid` (which internally call `__imp___RTtypeid`) and `dynamic_cast` (which internally call `__imp___RTDynamicCast `). as result you need use lib file, where this symbols is defined. `msvcurt.lib` or `vcruntime.lib`. and are your target platform is x64 ? – RbMm Oct 25 '17 at 21:48
  • @RbMm maybe I'm inexperienced, but shouldn't the compiler know of the library and import the symbols? I mean, typeid and dynamic_cast are part of the language... – Massimo Castrioto Oct 25 '17 at 22:06
  • @MassimoCastrioto - of course no. compiler don't know this and don't must know. and linker don't know. this you must know and add this lib to linker input. and your problem absolute not related to `inheritance` – RbMm Oct 25 '17 at 22:08
  • and for which target platform you build your code ? *x64* (*amd64*) ? – RbMm Oct 25 '17 at 22:20
  • What exact compile commands are you using? – aschepler Oct 25 '17 at 22:20
  • @aschepler - this absolute not related to any compiler options – RbMm Oct 25 '17 at 22:20
  • @RbMm Driver, then. One would normally use clang++ for the link step, and not link.exe directly. – aschepler Oct 25 '17 at 22:22
  • @aschepler and list of *libs* also can be defined in *clang++* ? in any case need found lib file, which containing this unresolved symbols and add to linker (or compiler) library list – RbMm Oct 25 '17 at 22:25
  • @RbMm Sure, you can pass library names to the clang++ driver. I haven't used clang on Windows, but on most systems if you use it for a link step, it will *automatically* add appropriate C++ and C runtime libraries. – aschepler Oct 25 '17 at 22:27
  • @aschepler - usually all *c/c++* use some run-time default library (depend from compiler option). but if some symbol not found - obvious he not containing in this library and need search lib where he is located. problem at all trivial – RbMm Oct 25 '17 at 22:30

2 Answers2

0

when you use dynamic_cast<Derived *>(base); in code compiler internally generate call [__imp___RTDynamicCast] instruction (this is for not x86 platform, for x86 will be call [__imp____RTDynamicCast] ). when you use typeid(base1) == typeid(base2) compiler generate call [__imp___RTtypeid] (on x86 platform will be call [__imp____RTtypeid]). when you begin link - linker view that in code used 2 symbols: __imp___RTDynamicCast and __imp___RTtypeid - he search it in all obj and lib files which you pass to him as input, but can not find. as result and give you error LNK2019: unresolved external symbol

you need search your crt lib files - which is containing exactly this strings - __imp____RTtypeid and __imp___RTDynamicCast - because exist very many different of crt versions - impossible say, which lib will be containing this symbols. say this can be msvcurt[d].lib or vcruntime[d].lib. may be in msvcrt.lib. all what you need - add one of this libs to linker input. and he find this symbols

RbMm
  • 31,280
  • 3
  • 35
  • 56
  • What you say makes sense, but now i'm trying to add either vcruntime.lib or msvcurt.lib to the linker output, and what happens is that it finds more definnitions for some other functions, like : libvcruntime.lib(std_type_info.obj) : error LNK2005: __std_type_info_compare already defined in vcruntime.lib(VCRUNTIME140_APP.dll) – Massimo Castrioto Oct 25 '17 at 22:29
  • @MassimoCastrioto - this is absolute normal - 2 libs conflict. you need use only **one** . remove `libvcruntime.lib` from default libs – RbMm Oct 25 '17 at 22:32
  • @MassimoCastrioto - you need use `/NODEFAULTLIB:libvcruntime.lib` in linker options or at all `/NODEFAULTLIB` and direct add `msvcurt.lib` or `vcruntime.lib` to linker. you must use only **one** crt lib – RbMm Oct 25 '17 at 22:37
  • @MassimoCastrioto - i try explain very basic and obvious things - every used symbol must be defined somewhere and only once. `libvcruntime.lib` not containing **all** symbols which you need. think `vcruntime.lib` or `msvcurt.lib` containing all symbols. but when you use 2+ crt libs at once - many symbols exist in several libs - linker simply don't know - which use and give you error LNK2005 - symbol already defined. if understand this - very easy resolve problem – RbMm Oct 25 '17 at 22:43
  • I understand that, what I do not understand is why do I have to tell the linker not to link the library vcruntime.lib by default, and then pass manually the same library? If I the compiler already links the library by default, why is it missing symbols? – Massimo Castrioto Oct 25 '17 at 23:04
  • @MassimoCastrioto - if you ask this - you still not understand. different libraries containing different symbols set. for example `__imp___RTDynamicCast` **not exist** in `libvcruntime.lib` but **exist** in `vcruntime.lib` and `msvcurt.lib` - so you need use one of this 2 libs. and compiler **never links any libs**. this do only linker. compiler can **indirect** pass `/DEFAULTLIB: libvcruntime.lib` directive to linker. but this will be superseded by `/NODEFAULTLIB` option. you need **remove** `libvcruntime.lib` and add `msvcurt.lib`. – RbMm Oct 25 '17 at 23:13
  • @MassimoCastrioto *why is it missing symbols* ? missing and all. strange question. why exist several crt libs ? why internal content of `libvcruntime.lib` != `msvcurt.lib` ? different libraries, different symbol sets.. *why do I have to tell the linker* - if you want resolve your problem - just do it as I say – RbMm Oct 25 '17 at 23:16
  • @MassimoCastrioto *why do I have to tell the linker not to link the library vcruntime.lib by default, and then pass manually the same library?* - look like you not understand. you must tell linker not use **libvcruntime.lib** by default. and pass manually **vcruntime.lib** - this is not the **same** library – RbMm Oct 25 '17 at 23:18
  • @MassimoCastrioto - however *vcruntime.lib* is too small. I think it not containing **all** symbols which you need. so you need use exactly *msvcurt.lib* – RbMm Oct 25 '17 at 23:21
  • yes, now I see what you say (I misread libvcruntime.lib and thought it was the same as vcruntime.lib), sorry for being stubborn. – Massimo Castrioto Oct 25 '17 at 23:37
  • @MassimoCastrioto - use exactly `msvcurt.lib`. I think `vcruntime.lib` not containing all symbols which you use(because it too small by size) – RbMm Oct 25 '17 at 23:38
0

I got this problem using Clang 5.0 Platform Toolset LLVM-VS2014 on Visual studio and also on CodeBlocks.

I added msvcrt.lib to provide the missing __imp____RTDynamicCast.

How one is supposed to deduce this, I have yet to understand :-(