poo modo metodos herencia derivadas codigo clases c++ types gdb superclass instanceof

modo - ¿Cómo determinar si un objeto es una instancia de cierta clase derivada de C++ desde un puntero a una clase base en GDB?



metodos en c++ (4)

Estoy depurando un programa C ++ con GDB.

Tengo un puntero a un objeto de cierta clase. El puntero se declara como de alguna clase superior que se extiende por varias subclases.

No hay campos en el objeto para especificar el tipo de clase preciso de este objeto, pero algunas funciones virtuales (por ejemplo, bool is_xxx ()) se definen para indicar el tipo de clase en tiempo de ejecución.

¿Hay alguna manera de decir el tipo de clase preciso de un objeto en GDB sin llamar a estas funciones virtuales? Llamar a tales funciones en GDB puede generar resultados confusos cuando el programa tiene múltiples subprocesos.


En mi sistema, ptype o whatis también solo muestran lo obvio.

(gdb) whatis pObject type = QObject *

Pero imprimir la primera entrada de la vtable me ayudó a:

(gdb) p /a (*(void ***)pObject)[0] $4 = 0xb4b4cdf4 <QMessageBox::metaObject() const>

Aquí el objeto apunta a un QMessageBox que se deriva de QObject. Esto solo funciona si la entrada vtable apunta a un método que la clase derivada anula.

Ver también: Imprimir tablas de C ++ usando GDB

Editar: Imprimir solo el puntero al vtable funciona de manera más confiable (aunque el resultado usa el nombre destrozado y no es tan legible):

(gdb) p /a (*(void ***)pObject) $5 = 0xb4af33a0 <_ZTV11QMessageBox+8>


No necesita llamar a las funciones virtuales, solo puede ver la dirección de la función virtual o vtable. Otra forma es usar RTTI


GDB 7.11

A partir de GDB 7.11, GCC 5.3.1, Ubuntu 16.04, haciendo solo:

p *myBase

en algo compilado con:

gcc -O0 -ggdb3

puede ser suficiente ya que muestra:

$1 = {_vptr.MyBase = 0x400c00 <vtable for MyDerived1+16>}

donde MyDerived1 es la clase derivada actual que estamos buscando.

Pero si lo haces además:

set print object on

la salida es aún más clara y se ve así:

$1 = (MyDerived1) {<MyBase> = {_vptr.MyBase = 0x400c00 <vtable for MyDerived1+16>}, <No data fields>}

Esto también afecta a otros comandos como:

ptype myBase

el cual muestra:

type = /* real type = MyDerived1 * */ class MyBase { public: virtual int myMethod(void); } *

en lugar de:

type = class MyBase { public: virtual int myMethod(void); } *

En este caso, no hubo ninguna indicación del tipo derivado sin set print object on .

whatis se ve afectado de manera similar

(gdb) whatis myBase type = MyBase * (gdb) set print object on (gdb) whatis myBase type = /* real type = MyDerived1 * */ MyBase *

Programa de prueba:

#include <iostream> class MyBase { public: virtual int myMethod() = 0; }; class MyDerived1 : public MyBase { public: virtual int myMethod() { return 1; } }; class MyDerived2 : public MyBase { public: virtual int myMethod() { return 2; } }; int main() { MyBase *myBase; MyDerived1 myDerived1; MyDerived2 myDerived2; myBase = &myDerived1; std::cout << myBase->myMethod() << std::endl; myBase = &myDerived2; std::cout << myBase->myMethod() << std::endl; }


Use ptype . Si lo usa solo, obtiene el tipo declarado del puntero:

(gdb) ptype ptr type = class SuperClass { // various members } *

Para señalar el tipo real del objeto, configure la variable "objeto de impresión":

(gdb) set print object on (gdb) ptype ptr type = /* real type = DerivedClass * */ class SuperClass { // various members } *