C++: как посмотреть содержимое vptr/vtable

Каждый объект C++, имеющий виртуальную функцию, имеет vptr, указывающий на vtable. Как я могу увидеть, что это за vptr и на что он указывает? Я понимаю, что это зависит от компилятора, и он может поместить vptr в любое место в пространстве памяти объекта. Но могу ли я найти, что это такое?

Ваше здоровье.


person madu    schedule 28.11.2014    source источник
comment
Почему вы хотите это сделать?   -  person Ed Heal    schedule 28.11.2014
comment
Каждый объект C++, который имеет виртуальную функцию, имеет vptr, указывающий на vtable. — сам стандарт C++ не диктует, как должна быть организована виртуальная диспетчеризация, так что это правда — насколько мне известно - из всех доступных в настоящее время компиляторов C++ и вероятно так и останется, но не с уверенностью, особенно, например. более простые программы, скомпилированные в одну единицу трансляции, где фактически не используется виртуальная диспетчеризация или RTTI во время выполнения.   -  person Tony Delroy    schedule 28.11.2014
comment
Спасибо. Я понимаю, что некоторые компиляторы предпочтут не выполнять динамическую привязку, если программа в этом не нуждается. Но мне нужно, как увидеть, что это за указатель, и увидеть его содержимое, когда существует vtpr/vtable.   -  person madu    schedule 28.11.2014
comment
У меня нет особой потребности в этом. Это чисто для понимания C++ на уровне объекта (хочу подтвердить то, что сказано в книге Lippmans C++ Object Model)   -  person madu    schedule 28.11.2014
comment
Вот еще одна из моих закладок, которая может вам понравиться — она объясняет один стандарт макета для информации VDT и RTTI: ABI для Itanium C++. Если вы хотите увидеть, что это за указатель и т. д., покопайтесь в gdb или любом другом отладчике, который вы используете....   -  person Tony Delroy    schedule 28.11.2014
comment
Спасибо ТониД. В отладке Visual Studio вы можете увидеть это содержимое в __vftable. Просто интересно, есть ли более простой способ сделать это в g++/gdb   -  person madu    schedule 28.11.2014


Ответы (1)


В этом конкретном случае у C есть одна vtable, а у A и B нет ни одной. Вы можете убедиться в этом сами, выделив функции-члены C вне строки, чтобы vtable действительно была сгенерирована, и исправив другие ошибки компиляции: extern "C" int puts(const char *);

struct A { virtual void func_1() = 0; };
struct B { virtual void func_2() = 0; };

struct C : A, B
{
  void func_1();
  void func_2();
};

... компиляция в объектный файл, а затем просмотр символов:

$ gcc -c test.cc
$ nm test.o | c++filt
                 U puts
0000000000000000 T C::func_1()
000000000000001a T C::func_2()
0000000000000033 T non-virtual thunk to C::func_2()
0000000000000000 V typeinfo for A
0000000000000000 V typeinfo for B
0000000000000000 V typeinfo for C
0000000000000000 V typeinfo name for A
0000000000000000 V typeinfo name for B
0000000000000000 V typeinfo name for C
0000000000000000 V vtable for C
                 U vtable for __cxxabiv1::__class_type_info
                 U vtable for __cxxabiv1::__vmi_class_type_info
    void C::func_1() { puts("func_1"); }
    void C::func_2() { puts("func_2"); }

С помощью вышеуказанных шагов вы можете найти контент, на который он указывает.

person ssg    schedule 11.08.2016
comment
На самом деле здесь две vtables: одна для A и одна для B. - person curiousguy; 03.09.2016