Eu costumo executar um programa como:
./a.out arg1 arg2 <file
Eu gostaria de depurá-lo usando o gdb.
Estou ciente da set args
funcionalidade, mas isso só funciona a partir do prompt gdb.
Eu costumo executar um programa como:
./a.out arg1 arg2 <file
Eu gostaria de depurá-lo usando o gdb.
Estou ciente da set args
funcionalidade, mas isso só funciona a partir do prompt gdb.
Respostas:
Passe os argumentos para o run
comando no gdb.
$ gdb ./a.out
(gdb) r < t
Starting program: /dir/a.out < t
$ gdb ./a.out
, o (gdb) r < t arg1 arg2
que funciona bem para mim. No meu caso a.out = nft
arg1 = import
arg2 = json
et = file containing json rules
Você consegue fazer isso:
gdb --args path/to/executable -every -arg you can=think < of
O ser mágico --args
.
Basta digitar run
no console de comando gdb para iniciar a depuração.
--args
, não há argumentos passados para o executável, por isso não é ambíguo.
argv[0]
é o nome do executável
gdb
si para o of
arquivo e resultar em gdb tentando executar comandos a partir dele
Se você deseja ter o run
comando bare gdb
para executar seu programa com redirecionamentos e argumentos, você pode usar set args
:
% gdb ./a.out
(gdb) set args arg1 arg2 <file
(gdb) run
Não consegui obter o mesmo comportamento com o --args
parâmetro, gdb
escapou ferozmente dos redirecionamentos, ou seja,
% gdb --args echo 1 2 "<file"
(gdb) show args
Argument list to give program being debugged when it is started is "1 2 \<file".
(gdb) run
...
1 2 <file
...
Este realmente redireciona a entrada do próprio gdb, não o que realmente queremos aqui
% gdb --args echo 1 2 <file
zsh: no such file or directory: file
Inicie o GDB em seu projeto.
Vá para o diretório do projeto, onde você já compilou o executável do projeto. Emita o comando gdb e o nome do executável como abaixo:
gdb projectExecutablename
Isso inicia o gdb, imprime o seguinte: GNU gdb (Ubuntu 7.11.1-0ubuntu1 ~ 16.04) 7.11.1 Copyright (C) 2016 Free Software Foundation, Inc. ............... .................................. Digite "palavra apropriada" para procurar comandos relacionados à "palavra". Lendo símbolos do projetoExecutablename ... done. (gdb)
Antes de iniciar a execução do programa, você deseja configurar seus pontos de interrupção. O comando break permite que você faça isso. Para definir um ponto de interrupção no início da função denominada main:
(gdb) b principal
Depois de ter o prompt (gdb), o comando run inicia a execução do executável. Se o programa que você está depurando exigir argumentos da linha de comando, especifique-os para o comando run. Se você deseja executar o meu programa no arquivo "xfiles" (que está em uma pasta "mulder" no diretório do projeto), faça o seguinte:
(gdb) r mulder / xfiles
Espero que isto ajude.
Isenção de responsabilidade: Esta solução não é minha, é adaptada de https://web.stanford.edu/class/cs107/guide_gdb.html Este pequeno guia para gdb foi, provavelmente, desenvolvido na Universidade de Stanford.
Não seria legal digitar debug
na frente de qualquer comando para poder depurá-lo gdb
no nível do shell?
Abaixo dela esta função. Até funciona com o seguinte:
"$program" "$@" < <(in) 1> >(out) 2> >(two) 3> >(three)
Esta é uma chamada em que você não pode controlar nada, tudo é variável, pode conter espaços, feeds de linha e metacaracteres de shell. Neste exemplo, in
, out
, two
, e three
são outros comandos arbitrários que consomem ou dados de produzir que não devem ser prejudicadas.
A bash
função a seguir chama gdb
quase de forma limpa em um ambiente como esse [ Gist ]:
debug()
{
1000<&0 1001>&1 1002>&2 \
0</dev/tty 1>/dev/tty 2>&0 \
/usr/bin/gdb -q -nx -nw \
-ex 'set exec-wrapper /bin/bash -c "exec 0<&1000 1>&1001 2>&1002 \"\$@\"" exec' \
-ex r \
--args "$@";
}
Exemplo de como aplicar isso: basta digitar debug
na frente:
Antes:
p=($'\n' $'I\'am\'evil' " yay ")
"b u g" "${p[@]}" < <(in) 1> >(out) 2> >(two) 3> >(three)
Depois de:
p=($'\n' $'I\'am\'evil' " yay ")
debug "b u g" "${p[@]}" < <(in) 1> >(out) 2> >(two) 3> >(three)
É isso aí. Agora é um acéfalo absoluto para depurar gdb
. Exceto por alguns detalhes ou mais:
gdb
não fecha automaticamente e, portanto, mantém o redirecionamento de entrada / saída aberto até você sair gdb
. Mas eu chamo isso de recurso.
Você não pode passar facilmente argv0
para o programa como com exec -a arg0 command args
. A seguir, faça este truque: Depois de exec-wrapper
alterar "exec
para "exec -a \"\${DEBUG_ARG0:-\$1}\"
.
Existem DFs acima de 1000 abertos, que normalmente são fechados. Se isso for um problema, altere 0<&1000 1>&1001 2>&1002
para ler0<&1000 1>&1001 2>&1002 1000<&- 1001>&- 1002>&-
Você não pode executar dois depuradores em paralelo. Também pode haver problemas, se algum outro comando consumir /dev/tty
(ou STDIN). Para corrigir isso, substitua /dev/tty
por "${DEBUGTTY:-/dev/tty}"
. Em algum outro tipo de TTY tty; sleep inf
e, em seguida, use o TTY impresso (ie. E. /dev/pts/60
) para depuração, como em DEBUGTTY=/dev/pts/60 debug command arg..
. Esse é o poder da Shell, se acostume!
Função explicada:
1000<&0 1001>&1 1002>&2
afasta os 3 primeiros FDs
0</dev/tty 1>/dev/tty 2>&0
restaura os 3 primeiros FDs para apontar para o seu TTY atual. Então você pode controlar gdb
./usr/bin/gdb -q -nx -nw
executa gdb
invoca gdb
no shell-ex 'set exec-wrapper /bin/bash -c "exec 0<&1000 1>&1001 2>&1002 \"\$@\""
cria um wrapper de inicialização, que restaura os 3 primeiros FDs salvos em 1000 e acima-ex r
inicia o programa usando o exec-wrapper
--args "$@"
passa os argumentos como dadoIsso não foi fácil?
r
é curtorun
e você pode segui-lo com qualquer argumento. Como nesta questão, seria:r arg1 arg2 <file
ou poderia serrun arg1 arg2 <file