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?

Paolo Tedesco
fonte

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

jpalecek
fonte
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.

Jonathan Wakely
fonte
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) 
Mr.Ree
fonte
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
Russo empregado
fonte
12

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

anand
fonte
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.

Mazhar MIK
fonte
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.

Dan
fonte
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