3

I read from "Inside The C++ Object Model" that the type_info object is often stored at the first slot of the virtual table. However, I iterated the members in the virtual table:

class Base {
public:
    virtual void f() { cout << "Base::f" << endl; }
    virtual void g() { cout << "Base::g" << endl; }
    virtual void h() { cout << "Base::h" << endl; }
};

typedef void(*Fun)(void);

Base b;

(Fun)*((int*)*(int*)(&b)+0); // Base::f()
(Fun)*((int*)*(int*)(&b)+1); // Base::g()
(Fun)*((int*)*(int*)(&b)+2); // Base::h()

As you see from the last three lines, I can't find type_info at all.

Mu Qiao
  • 6,941
  • 1
  • 31
  • 34
  • 5
    what hinders the compiler to put it at -1 ? check the generated assembler code when you access type_info... – Yahia Aug 23 '11 at 02:25
  • There is http://stackoverflow.com/q/6258559/196561 the copy of description of all vtable/vtabletable and type_info pointers. – osgx May 14 '13 at 02:27

3 Answers3

6

There is no cross-compiler way to get at the type_info from the address of an object. Nor would you expect there to be; the way to get a type_info is using a specific C++ keyword: typeid.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • So is type_info actually stored anywhere? I think most of the time the compiler knows enough information so that typeid(whatever) can be optimized out at compile time. – Mu Qiao Aug 23 '11 at 02:30
  • 3
    Yes, a `type_info` is "stored somewhere". It is a real object that the compiler must create storage for. But more than likely, it is stored in global data, since `type_info` objects must exist until the end of execution. – Nicol Bolas Aug 23 '11 at 02:38
  • @Nicol yeah I think that too, since you can't copy them (`type_info`s)but you can return references to them which indicates they exist somewhere independently. – Seth Carnegie Aug 23 '11 at 02:41
1
#include <iostream>
#include <typeinfo>
using namespace std;
class Base {
    public:
        virtual void f() { cout << "Base::f" << endl; }
        virtual void g() { cout << "Base::g" << endl; }
        virtual void h() { cout << "Base::h" << endl; }
};

int main(void)
{
    typedef void(*Fun)(void);
    Fun pFun = NULL;
    Base b;

    pFun = (Fun)(*((long *)(*((long *)(&b))) + 0));
    pFun();//Base::f()
    pFun = (Fun)(*((long *)(*((long *)(&b))) + 1));
    pFun();//Base::g()
    pFun = (Fun)(*((long *)(*((long *)(&b))) + 2));
    pFun();//Base::h()

    type_info *base_type = (type_info *)(*((long *)(*((long *)(&b))) - 1));
    cout << "typeinfo is:" << base_type->name() << endl;

    cout << "the result of typeid(Base).name():" << typeid(Base).name() << endl;
    return 0;
}

the output is:

Base::f
Base::g
Base::h
typeinfo is:4Base
the result of typeid(Base).name():4Base

I use GCC 4.9.2 and my system is 64bit. so I use long instead of int.

type_info object is often stored at the first slot of the virtual table.

This is wrong I think.
type_info object is often stored before the virtual table.
(long *)(*((long *)(&b))):this is the address of virtual table
(long *)(*((long *)(&b))) - 1:this is the address of type_info object
so you see the result of the base_type->name() is 4Base. The result is the same as using typeid.The 4 in 4Base is the number of letters in your class name(Base).more info here

ALSO: when you complie the code with -fdump-class-hierarchy,you could see the Vtable for Base

Vtable for Base
Base::_ZTV4Base: 5u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI4Base)
16    (int (*)(...))Base::f
24    (int (*)(...))Base::g
32    (int (*)(...))Base::h

You could see _ZTI4Base is before Base::f
use c++filt _ZTI4Base would output typeinfo for Base

Community
  • 1
  • 1
JCRunner
  • 125
  • 1
  • 1
  • 7
-1

type_info is available only if you enable RTTI(runtime type information) compilation flag for some compilers.

Nicolae Dascalu
  • 3,425
  • 2
  • 19
  • 17
  • 4
    Note that not "enabling" the RTTI stops your compiler from being conformant with the standard. While many compilers do support turning of RTTI as an extension, the _language_ does not. – Nicol Bolas Aug 23 '11 at 02:39
  • @Nicol Bolas: so for testing purpose only, to see address of type_info into vtable (as most of compiler implement it) you need RTTI enabled. – Nicolae Dascalu Aug 23 '11 at 03:03