Inspeccionar el contenido del contenedor estándar (std :: map) con gdb

93

Suponiendo tener algo como esto:

#include <map>
int main(){
    std::map<int,int> m;
    m[1] = 2;
    m[2] = 4;
    return 0;
}

Me gustaría poder inspeccionar el contenido del mapa que ejecuta el programa desde gdb.
Si intento usar el operador de subíndice, obtengo:

(gdb) p m[1]
Attempt to take address of value not located in memory.

Usar el método de búsqueda no produce mejores resultados:

(gdb) p m.find(1)
Cannot evaluate function -- may be inlined

¿Hay alguna manera de lograr esto?

Paolo Tedesco
fuente

Respuestas:

35

Creo que no lo hay, al menos no si su fuente está optimizada, etc. Sin embargo, hay algunas macros para gdb que pueden inspeccionar los contenedores STL por usted:

http://sourceware.org/ml/gdb/2008-02/msg00064.html

Sin embargo, no uso esto, entonces YMMV

jpalecek
fuente
1
Gracias por el enlace; lo único es que las macros dependen de la versión de las bibliotecas stl, que preferiría evitar. +1
Paolo Tedesco
También es un poco frustrante que comandos como "plist foo std :: string" den errores de sintaxis. Parece que value_type no puede contener ningún signo de puntuación.
Bklyn
2
No lo he intentado, pero si esto funciona igual que el resto de GDB, encerrar el nombre entre comillas simples debería hacerlo.
jpalecek
2
Nota: la funcionalidad std :: map en estos scripts asume tipos de puntero de 32 bits. Para máquinas de 64 bits, reemplace "+ 4" por "+ 8" en todas partes del archivo.
Kyle Simek
pvector no está definido en mi gdb (versión 7.5.91.20130417-cvs-ubuntu).
Jeff
91

Las respuestas existentes a esta pregunta están muy desactualizadas. Con un GCC y GDB recientes, Just Works TM gracias al soporte integrado de Python en GDB 7.xy las bonitas impresoras libstdc ++ que vienen con GCC.

Para el ejemplo de OP obtengo:

(gdb) print m
$1 = std::map with 2 elements = {[1] = 2, [2] = 4}

Si no funciona automáticamente, verá el primer punto en la página de soporte de STL del wiki de GDB.

También puede escribir impresoras bonitas Python para sus propios tipos, consulte Impresión bonita en el manual de GDB.

Jonathan Wakely
fuente
2
Sí, pero otras preguntas se están cerrando como duplicados, así que quería que tuviera información reciente.
Jonathan Wakely
1
Estoy usando GDB 7.2 y lo anterior funciona ... si tiene una colección pequeña. Todavía no he encontrado ninguna forma de imprimir, por ejemplo, el elemento 1543 desde un vector 4K, aparte de recurrir al uso de estructuras internas de la implementación de STL.
Pabellón
5
Sí, en GDB 7.2 y el compilador icpc obtengo el error Could not find operator[].
Pabellón
11
Desafortunadamente, no "Simplemente funciona" en todas las distribuciones. No está instalado de forma predeterminada en Ubuntu 13.10 y hay problemas cuando intenta instalarlo manualmente
nietaki
1
@razeh, Fedora, RHEL (y clones de RHEL). Hay una solución en progreso para que las impresoras también funcionen en distribuciones donde GDB está vinculado a Python 3
Jonathan Wakely
25

Siempre está lo obvio: Defina su propia función de prueba ... Llámelo desde gdb. P.ej:

#define SHOW(X) cout << # X " = " << (X) << endl

void testPrint( map<int,int> & m, int i )
{
  SHOW( m[i] );
  SHOW( m.find(i)->first );
}

int
main()
{
    std::map<int,int> m;
    m[1] = 2;
    m[2] = 4;
    return 0;  // Line 15.
}

Y:

....
Breakpoint 1 at 0x400e08: file foo.C, line 15.
(gdb) run
Starting program: /tmp/z/qD 

Breakpoint 1, main () at qD.C:15
(gdb) call testPrint( m, 2)
m[i] = 4
(*m.find(i)).first = 2
(gdb) 
Señor ree
fuente
16
siempre que el proceso se esté ejecutando. no es tan útil para los volcados de memoria.
sean riley
2
Este es un consejo útil para depurar GDB en general, no solo con STL. Guardo una biblioteca completa de funciones auxiliares de gdb para muchos datos difíciles de recuperar, por ejemplo, write_cuda_array_as_image (). Tenga en cuenta que algunos compiladores eliminarán las funciones que no se llaman, por lo que hago una llamada a cada función auxiliar después del "return 0;" de mi main. Además, declararlos con extern "C" facilita la llamada desde gdb.
Kyle Simek
21

El stl-views.gdbsolía ser la mejor respuesta que había, pero ya no.

Esto aún no está integrado en la línea principal GDB, pero esto es lo que obtienes usando la rama 'archer-tromey-python' :

(gdb) list
1   #include <map>
2   int main(){
3       std::map<int,int> m;
4       m[1] = 2;
5       m[2] = 4;
6       return 0;
7   }
(gdb) break 6
Breakpoint 1 at 0x8048274: file map.cc, line 6.
(gdb) run

Breakpoint 1, main () at map.cc:6
6       return 0;
(gdb) print m
$1 = std::map with 2 elements = {
  [1] = 2,
  [2] = 4
}
(gdb) quit
Ruso empleado
fuente
12

Intente eliminar la referencia a los contenedores STL: en esta página: http://www.yolinux.com/TUTORIALS/GDB-Commands.html

anand
fuente
¡Estos parecen ser el negocio!
Richard Corden
En realidad, son las mismas macros que en la respuesta anterior :) Me temo que no hay una solución más simple.
Paolo Tedesco
¿Qué es el comando? Se las arregló para llevarnos fuera del sitio con grandes cantidades de información irrelevante. No estoy interesado en "Cómo iniciar GDB" y los demás.
jww
1

Las respuestas anteriores funcionan y están bien. En caso de que esté utilizando stl-views.gdb, esta es la forma correcta de ver los mapas y los elementos que contiene. Deje que su mapa sea el siguiente: std::map<char, int> myMap;

(gdb) pmap myMap char int

es decir, pmap <variable_name> <left_element_type> <right_element_type>ver los elementos en el mapa.

Espero que ayude.

Mazhar MIK
fuente
0

Puede solucionar el segundo problema ( Cannot evaluate function -- may be inlined) asegurándose de que su compilador use información de depuración DWARF-2 (o 3 o 4) cuando compile su programa. DWARF-2 incluye información en línea, por lo que debería poder utilizar cualquiera de los métodos que describió para acceder a los elementos de su std::mapcontenedor.

Para compilar con la información de depuración de DWARF-2, agregue la -gdwarf-2bandera a su comando de compilación.

Dan
fuente
1
Um, saber dónde se ha insertado una función no hace posible que GDB evalúe las llamadas a esa función; ¡GDB realmente necesita acceso a una copia fuera de línea de la función!
SamB