Você está na página 1de 5

20/03/2019

Introdução

▪ Boas práticas de programação


▪ Reduzem chance de erros (eles vão existir!)
Programação e Desenvolvimento de Software 2 ▪ Medidas proativas
Estratégias de depuração e ferramentas ▪ Programação defensiva
Prof. Douglas G. Macharet
douglas.macharet@dcc.ufmg.br ▪ Testes de unidade
▪ Meu programa não funciona! E agora?!
▪ Vou reescreer tudo do zero!
▪ Medidas reativas
▪ Depuração

PDS 2 - Estratégias de depuração e ferramentas 2

Depuração Depuração
Motivação

▪ Verificação e validação ▪ Depurar grandes programas é difícil (arte?)


▪ Relacionados ao estabelecimento da existência ▪ Um bom programador deve conhecer uma
de falhas (inconsistências) em um programa ampla variedade de estratégias de depuração
▪ Depuração (debugging) ▪ Um bom programador deve conhecer/usar
▪ Relacionado à localização e reparação de falhas ferramentas que facilitam a depuração
▪ Debuggers
▪ Sistemas de controle de versão
▪ IDEs
Primeiro bug na computação (Harvard Mark II).
A Arte de Depurar: https://msdn.microsoft.com/pt-br/library/cc517980.aspx

PDS 2 - Estratégias de depuração e ferramentas 3 PDS 2 - Estratégias de depuração e ferramentas 4

Depuração Depuração vs. Testes


Quando realizar

▪ Código dá crash, parando a execução ▪ Depurar (detetive)


▪ Resultados diferentes dos esperados ▪ O que fazer para tentar consertar o programa?
▪ Necessidade de melhorar o desempenho ▪ Testar (vândalo)
▪ O que fazer para tentar quebrar o programa?
▪ Entender melhor como o código funciona

When debugging, novices insert corrective code;


experts remove defective code.
– R. Pattis

PDS 2 - Estratégias de depuração e ferramentas 5 PDS 2 - Estratégias de depuração e ferramentas 6

1
20/03/2019

Depuração Depuração
Tipos de erros Tipos de erros – Sintáticos

▪ Sintáticos
▪ Erros associados ao fato de que a sintaxe da
linguagem não está sendo respeitada int main() { int main() {

▪ Semânticos int a = 5 int x = (3 + 5;

▪ Erros associados a um uso indevido de algumas return 0; return 0;


declarações do programa } }
• Falta adicionar ‘;’ ao final. • Falta fechar o parênteses.
▪ Lógica
▪ Erros associados ao fato de que a especificação
(comportamento desejado) não é respeitada
PDS 2 - Estratégias de depuração e ferramentas 7 PDS 2 - Estratégias de depuração e ferramentas 8

Depuração Depuração
Tipos de erros – Sintáticos Tipos de erros – Semânticos

▪ Leia e entenda as mensagens de erro!


int main() {
main.cpp: In function ‘int main()’: int main() {
main.cpp:15:3: error: expected ‘,’ or ‘;’ before ‘return’ int i;
return 0; int a = "hello";
i++;
^ return 0;
return 0;
}
}
• -Wall: Exibe na tela todos os warnings que ele encontrar no código. Um
• Variável não inicializada. • Atribuição incorreta de tipo.
warning não é um erro, mas sim uma advertência sobre o uso incorreto (não
• Ocorre apenas um Warning. • Erro de compilação.
recomendado) de alguma função/instrução da linguagem.
• -pedantic: Esta flag faz com que o compilador seja mais “pedante”,
emitindo warnings para todas as partes do código que podem estar erradas.

PDS 2 - Estratégias de depuração e ferramentas 9 PDS 2 - Estratégias de depuração e ferramentas 10

Depuração Depuração
Tipos de erros – Momento da detecção Tipos de erros – Momento da detecção

▪ Tempo de compilação
▪ Erros de sintaxe e erros semânticos estáticos int main() {

são indicados pelo próprio compilador int a, b, x;

▪ Tempo de execução
a = 10;
b = 0;
▪ Erros semânticos dinâmicos e erros lógicos não x = a / b;

podem ser detectados pelo compilador (difícil) return 0;


}
▪ É necessário depurar o código! O programa compila, e o problema só será
detectado durante a execução do programa.

PDS 2 - Estratégias de depuração e ferramentas 11 PDS 2 - Estratégias de depuração e ferramentas 12

2
20/03/2019

Depuração Depuração
Tipos de erros – Lógica Estratégias

▪ Geralmente detectados durante execução ▪ Reproduzir o problema


▪ Retorno de um resultado incorreto ▪ Determinar condições / Estabilizar
▪ Loops infinitos ▪ Identificar o local e provável causa
▪ Segmentation fault ▪ Dados → Hipótese → Experimentos (repetir)
▪ Geralmente bastante imprevisíveis ▪ Fazer a correção do erro
▪ De acordo com entradas (bem) específicas ▪ Considerar a real razão do problema
▪ Dependentes de plataforma ou hardware
▪ Avaliar a solução e procurar erros similares
▪ Cuidado com possíveis efeitos colaterais!

PDS 2 - Estratégias de depuração e ferramentas 13 PDS 2 - Estratégias de depuração e ferramentas 14

Depuração Depuração
Estratégias Estratégias (raiz)

▪ printf / cout
▪ “Acompanhamento” da execução do programa
▪ Selecionar pontos chave alcançados ou não, exibir
os valores de variáveis importantes
▪ Prós
▪ Simples, fácil e rápido
▪ Cons
▪ Pode prejudicar a legibilidade do código
▪ Várias compilações para diferentes testes
▪ Não é possível pausar ou controlar a execução
▪ Não é possível modificar valores de variáveis

PDS 2 - Estratégias de depuração e ferramentas 15 PDS 2 - Estratégias de depuração e ferramentas 16

Depuração Depuração
Exemplo 1 Exemplo 1

▪ Calcular o valor da seguinte série #include <iostream>


#include <cmath>
▪ Esse código funciona?
▪ Entradas: 𝑥 e 𝑛
int main() {
using namespace std;
cout << series(2, 3) << endl;
int fatorial(int n) { return 0;
int fat = 0; }
𝑥 0 𝑥1 𝑥 2 𝑥𝑛 for (int i = 1; i < n; i++)

+ + + ⋯+ fat = fat * i;
return fat; ▪ Como descobrir o erro?
0! 1! 2! 𝑛! }
▪ fatorial(int n)
double series(double x, int n) { ▪ int fat = 1;

▪ Por onde começar?


double xpow, seriesValue;
▪ for (int i = 1; i <= num; i++)
for (int k = 1; k <= n; k++) {
▪ series(double x, int n)
▪ Modularizar em 2 funções xpow = pow(x, k);
seriesValue += xpow / fatorial(k); ▪ for (int k = 0; k <= n; k++)
}
▪ double seriesValue = 0.0;
return seriesValue;
}

PDS 2 - Estratégias de depuração e ferramentas 17 PDS 2 - Estratégias de depuração e ferramentas 18

3
20/03/2019

Depuração GDB
Dicas gerais

▪ Pense antes de escrever ▪ GNU Debugger


▪ Procure por problemas comuns ▪ Depurador “padrão” de C/C++
▪ Dividir para conquistar ▪ Permite acompanhar o que está acontecendo
dentro do programa enquanto é executado
▪ Adicione mais testes internos
▪ Adicionar breakpoints
▪ Mostre o valor de variáveis importantes ▪ Analisar o código uma linha de cada vez
▪ Concentre-se em mudanças recentes ▪ Verificar valores de variáveis durante a execução
▪ Utilize ferramentas auxiliares
https://www.gnu.org/software/gdb/
https://betterexplained.com/articles/debugging-with-gdb/

PDS 2 - Estratégias de depuração e ferramentas 19 PDS 2 - Estratégias de depuração e ferramentas 20

GDB GDB
Exemplo – Identifique e corrija os erros!

▪ Pode ser utilizado pela linha de comando


▪ Utilizar a flag de compilação “-g” (debug)
#include<iostream> int main() {

using namespace std; int arr[5] = {17, 21, 44, 2, 60};

int findMax(int *array, int len, int max) { int max;


max = array[0]; if (findMax(arr, 5, max) != 0) {
for(int i=1; i <= len; i++) { cout << "Ocorreu erro!" << endl;
if(max < array[i]) { exit(1);
max = array[i]; }
}
} cout << "Valor maximo e: " << max << endl;

return 0;
▪ Ferramentas auxiliares
return 0;
} }

▪ https://gdbgui.com
▪ https://www.onlinegdb.com/ $ g++ -std=c++11 -g gdbExample.cpp -o gdbExample
$ gdb gdbExample

PDS 2 - Estratégias de depuração e ferramentas 21 PDS 2 - Estratégias de depuração e ferramentas 22

Valgrind Valgrind
Exemplo 1 – Identifique e corrija os erros!

▪ Ferramentas que ajudam a detectar erros


#include<iostream>
associados ao gerenciamento de memória using namespace std;
▪ Memory leak, erros alocação ou desalocação, ... int main() {

▪ Ferramentas auxiliares
int a[10];
for (int i = 0; i < 9; i++)
a[i] = i;
▪ Valkyrie: http://valgrind.org/downloads/guis.html for (int i = 0; i < 10; i++){

▪ Dr. Memory: http://drmemory.org/ }


cout << a[i] << endl;

return 0;
}

$ g++ -std=c++11 -g valgrind_ex01.cpp -o valgrind_ex01


$ valgrind --leak-check=full ./valgrind_ex01

http://valgrind.org/docs/manual/quick-start.html http://valgrind.org/docs/manual/mc-manual.html#mc-manual.uninitvals

PDS 2 - Estratégias de depuração e ferramentas 23 PDS 2 - Estratégias de depuração e ferramentas 24

4
20/03/2019

Valgrind Valgrind
Exemplo 2 – Identifique e corrija os erros! Exemplo 3 – Identifique e corrija os erros!
#include<iostream>

using namespace std;


#include<list>
struct TADExemplo {
int atributo; using namespace std;
};
struct TADExemplo {
int main() { int atributo;
TADExemplo *c = new TADExemplo();
};
c->atributo = 10;

delete c; int main() {

cout << c->atributo << endl; list<TADExemplo*> itens;


c->atributo = 99;
itens.push_back(new TADExemplo());
cout << c->atributo << endl;
itens.push_back(new TADExemplo());
delete c;
return 0;
return 0; }
}

https://en.wikipedia.org/wiki/Undefined_behavior
http://valgrind.org/docs/manual/mc-manual.html#mc-manual.badrw http://valgrind.org/docs/manual/mc-manual.html#mc-manual.leaks

PDS 2 - Estratégias de depuração e ferramentas 25 PDS 2 - Estratégias de depuração e ferramentas 26

Considerações finais Considerações finais


Como NÃO fazer depuração

▪ Encontrar defeitos adivinhando (na sorte)


▪ Fazer alterações aleatórias até funcionar
▪ Não fazer um backup do original e não
manter um histórico das alterações feitas
▪ Corrigir o erro com a solução mais óbvia e
simples, sem entender a razão do problema
▪ O sintoma é removido, mas não a causa
▪ O erro “sumiu”, o problema está resolvido! https://xkcd.com/1739/

PDS 2 - Estratégias de depuração e ferramentas 27 PDS 2 - Estratégias de depuração e ferramentas 28

Você também pode gostar