Inspecionando o conteúdo do contêiner padrão (std :: map) com gdb


93

Supondo que tenha algo assim:

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

Eu gostaria de poder inspecionar o conteúdo do mapa executando o programa do gdb.
Se tento usar o operador subscrito, obtenho:

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

Usar o método find não produz melhores resultados:

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

Existe uma maneira de fazer isso?

Respostas:


35

Eu acho que não há, pelo menos não se sua fonte for otimizada etc. No entanto, existem algumas macros para gdb que podem inspecionar contêineres STL para você:

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

No entanto, eu não uso isso, então YMMV


1
Obrigado pelo link; a única coisa é que as macros são dependentes da versão das bibliotecas stl, que eu prefiro evitar. +1
Paolo Tedesco

Também é um pouco frustrante que comandos como "plist foo std :: string" apresentem erros de sintaxe. Parece que value_type não pode conter nenhuma pontuação.
Bklyn

2
Eu não tentei, mas se isso funcionar da mesma forma que o resto do GDB, colocar o nome pontuado entre aspas simples deve funcionar.
jpalecek

2
Nota: a funcionalidade std :: map nesses scripts assume tipos de ponteiro de 32 bits. Para máquinas de 64 bits, substitua "+ 4" por "+ 8" em todo o arquivo.
Kyle Simek

pvector não está definido no meu gdb (versão 7.5.91.20130417-cvs-ubuntu).
Jeff

91

As respostas existentes para esta pergunta estão muito desatualizadas. Com um GCC e GDB recentes, ele simplesmente funciona TM, graças ao suporte Python integrado no GDB 7.xe às belas impressoras libstdc ++ que vêm com o GCC.

Para o exemplo do OP eu recebo:

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

Se não funcionar automaticamente para você, veja o primeiro ponto na página de suporte STL do wiki GDB.

Você também pode escrever impressoras bonitas em Python para seus próprios tipos, consulte Pretty Printing no manual do GDB.


2
Sim, mas outras questões estão sendo fechadas como duplicatas dele, então eu queria ter informações recentes.
Jonathan Wakely

1
Estou usando o GDB 7.2 e o procedimento acima funciona ... se você tiver uma coleção pequena. Eu ainda não encontrei nenhuma maneira de imprimir, digamos, o elemento 1543 de um vetor 4K, além de recorrer ao uso de estruturas internas da implementação STL.
pavon,

5
Sim, no GDB 7.2 e no compilador icpc recebo o erro Could not find operator[].
pavon

11
Infelizmente, isso não "simplesmente funciona" em todas as distros. Não é instalado por padrão no Ubuntu 13.10 e há problemas quando você tenta instalá-lo manualmente
nietaki

1
@razeh, Fedora, RHEL (e clones do RHEL). Há uma correção em andamento para fazer com que as impressoras também funcionem em distros onde o GDB está vinculado ao Python 3
Jonathan Wakely

25

Sempre há o óbvio: Defina sua própria função de teste ... Chame-a do gdb. Por exemplo:

#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.
}

E:

....
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) 

16
enquanto o processo estiver em execução. não é tão útil para core-dumps.
sean riley

2
Este é um conselho útil para depurar GDB em geral, não apenas com STL. Eu mantenho uma biblioteca inteira de funções auxiliares do gdb para muitos dados difíceis de recuperar, por exemplo, write_cuda_array_as_image (). Observe que alguns compiladores removerão quaisquer funções que não sejam chamadas, então eu coloco uma chamada para cada função auxiliar após o "return 0;" de meu main. Declará-los também com extern "C" torna mais fácil chamá-los a partir do gdb.
Kyle Simek de

21

A stl-views.gdbcostumava ser a melhor resposta que havia, mas não mais.

Isso não está integrado na linha principal GDBainda, mas aqui é o que se obtém usando o 'arqueiro-tromey-python' ramo :

(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

12

Tente remover a referência de contêineres STL: nesta página: http://www.yolinux.com/TUTORIALS/GDB-Commands.html


Estes parecem ser o negócio!
Richard Corden

Na verdade, são as mesmas macros da resposta anterior :) Infelizmente, não há uma solução mais simples.
Paolo Tedesco

Qual é o comando? Você conseguiu nos manter fora do local com uma grande quantidade de informações irrelevantes. Não estou interessado em "Como iniciar o GDB" e em outros.
jww

1

As respostas acima estão funcionando e bem. Caso você esteja usando stl-views.gdb, aqui está a maneira adequada de visualizar os mapas e elementos dentro dele. Deixe o seu mapa ser o seguinte: std::map<char, int> myMap;

(gdb) pmap myMap char int

ou seja, pmap <variable_name> <left_element_type> <right_element_type>para ver os elementos no mapa.

Espero que ajude.


0

Você pode contornar o segundo problema ( Cannot evaluate function -- may be inlined) certificando-se de que seu compilador usa informações de depuração DWARF-2 (ou 3 ou 4) ao compilar seu programa. DWARF-2 inclui informações embutidas, portanto, você deve ser capaz de usar qualquer um dos métodos descritos para acessar os elementos do seu std::mapcontêiner.

Para compilar com informações de depuração DWARF-2, adicione o -gdwarf-2sinalizador ao seu comando de compilação.


1
Hum, saber onde uma função foi embutida não torna possível para o GDB avaliar as chamadas para essa função; GDB realmente precisa de acesso a uma cópia fora de linha da função!
SamB
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.