aprende a usar gdb, el depurador de c

67
¿Por qué no funciona mi práctica? Aprende a usar el depurador de C: GDB by @sgomez

Upload: sergio-gomez

Post on 14-Jul-2015

137 views

Category:

Education


0 download

TRANSCRIPT

¿Por qué no funciona mi práctica?

Aprende a usar el depurador de C: GDB

by @sgomez

¿Quién soy?

¿Quién soy?

Sergio Gómez @sgomez

KEEP

KEEPCALMAND

SEGMENTATIONFAULT

KEEPCALMAND

AVOIDSEGMENTATION

FAULT

¿Cómo se produce un Segmentation Fault?

Básicamente al acceder a una zona de memoria a la que no tenemos acceso.

¿Cómo se produce un Segmentation Fault?

Acceso a memoria de solo lectura

int main(void) { char *s = "hello world"; *s = 'H'; // Segfault }

¿Cómo se produce un Segmentation Fault?

Acceso a memoria de solo lectura

int main(void) { char s[] = "hello world"; *s = 'H'; // OK }

¿Cómo se produce un Segmentation Fault?

Referencias a punteros nulos

int main(void) { int *ptr = NULL; printf("%d", *ptr); // Segfault }

¿Cómo se produce un Segmentation Fault?

Desbordamiento de bufferint main(void) { char A[8] = ""; unsigned short B = 1979; strcpy(A, "excessive"); }

¿Cómo se produce un Segmentation Fault?

Desbordamiento de bufferint main(void) { char A[8] = ""; unsigned short B = 1979; strcpy(A, "excessive"); }

¿Cómo se produce un Segmentation Fault?

Desbordamiento de pila

int main(void) { main(); return 0; }

int main(void) { char *ptr = (char *) malloc (sizeof(char) * 4); }

¿Cuál es el tamaño en bytes del bloque de memoria reservado para ptr?

4 bytes 5 bytes (4 + ‘/0’)

Más de 5 Ninguna es correcta

int main(void) { char *ptr = (char *) malloc (sizeof(char) * 4); }

¿Cuál es el tamaño en bytes del bloque de memoria reservado para ptr?

5 bytes (4 + ‘/0’)

Más de 5

int main(void) { char *ptr = (char *) malloc (sizeof(char) * 4); }

¿Cuál es el tamaño en bytes del bloque de memoria reservado para ptr?

Más de 5

Empezamos… ¡Tenemos un bug!

function keep_calm() { printf (“KEEP\n”); printf (“CALM\n”); printf (“AND\n”); keep_calm();}

Razones para no usar printf

Razones para no usar printf

1) No es una herramienta de depuración

Razones para no usar printf

1) No es una herramienta de depuración2) Nos obliga a ir probando para acotar el fallo

Razones para no usar printf

1) No es una herramienta de depuración2) Nos obliga a ir probando para acotar el fallo

3) Nos puede engañar

int mi_funcion(int *array, char *array2) {

asdasdksd saj dhljkdh sd has d SDa sd

asd asd asdasd sad adds sad sadsad sdas

asdasdasds adSD SDsd asdas dsad

d aSDSADASD ASD DDSDSADJKSHDKL JKSAHD JHJADHASD

ASDHASJDHKJASDHASKJDHAS

DASDJÑASKLDJAKSLDJÑALSKDJÑASKLDJASKDJAKSDJÑALSD

ASDÑKASDJÑLKASDJÑASKDJ

sadkjadsÑKLjdsadkalsdjñlaskjdñaskldjñalS

ASDKJÑDKLJasñkdljsñkdjasñkld

askljd ska ids ajdk sdjsakdñad }

int mi_funcion(int *array, char *array2) {

asdasdksd saj dhljkdh sd has d SDa sd printf(“A”);

asd asd asdasd sad adds sad sadsad sdas

asdasdasds adSD SDsd asdas dsad printf(“B”);

d aSDSADASD ASD DDSDSADJKSHDKL JKSAHD JHJADHASD

ASDHASJDHKJASDHASKJDHAS printf(“C”);

DASDJÑASKLDJAKSLDJÑALSKDJÑASKLDJASKDJAKSDJÑALSD

ASDÑKASDJÑLKASDJÑASKDJ

sadkjadsÑKLjdsadkalsdjñlaskjdñaskldjñalS printf(“D”);

ASDKJÑDKLJasñkdljsñkdjasñkld

askljd ska ids ajdk sdjsakdñad }

bash$ gcc code.c -o code

bash$ gcc code.c -o codebash$ ./code

bash$ gcc code.c -o codebash$ ./codeAB

bash$ gcc code.c -o codebash$ ./codeABSegmentation fault.

bash$ gcc code.c -o codebash$ ./codeABSegmentation fault.bash$

bash$ gcc code.c -o code bash$ ./code AB Segmentation fault. bash$

¿Dónde está el fallo?

Entre A y B Entre B y C

Entre C y D Ninguna es correcta

int mi_funcion(int *array, char *array2) { printf(“A”);

asdasdasds adSD SDsd asdas dsad printf(“B”);

ASDHASJDHKJASDHASKJDHAS printf(“C”);

sadkjadsÑKLjdsadkalsdjñlaskjdñaskldjñalS printf(“D”);

askljd ska ids ajdk sdjsakdñad }

bash$ gcc code.c -o code bash$ ./code AB Segmentation fault. bash$

¿Dónde está el fallo?

Entre C y D Ninguna es correcta

int mi_funcion(int *array, char *array2) { printf(“A”);

asdasdasds adSD SDsd asdas dsad printf(“B”);

ASDHASJDHKJASDHASKJDHAS printf(“C”);

sadkjadsÑKLjdsadkalsdjñlaskjdñaskldjñalS printf(“D”);

askljd ska ids ajdk sdjsakdñad }

bash$ gcc code.c -o code bash$ ./code AB Segmentation fault. bash$

¿Dónde está el fallo?

Ninguna es correcta

int mi_funcion(int *array, char *array2) { printf(“A”);

asdasdasds adSD SDsd asdas dsad printf(“B”);

ASDHASJDHKJASDHASKJDHAS printf(“C”);

sadkjadsÑKLjdsadkalsdjñlaskjdñaskldjñalS printf(“D”);

askljd ska ids ajdk sdjsakdñad }

printf usa el canal stdoutint mi_funcion(int *array, char *array2) { printf(“A”);

asdasdasds adSD SDsd asdas dsad printf(“B”);

ASDHASJDHKJASDHASKJDHAS printf(“C”);

sadkjadsÑKLjdsadkalsdjñlaskjdñaskldjñalS printf(“D”);

askljd ska ids ajdk sdjsakdñad }

Buffer

Consola

printf usa el canal stdoutint mi_funcion(int *array, char *array2) { printf(“A”);

asdasdasds adSD SDsd asdas dsad printf(“B”);

ASDHASJDHKJASDHASKJDHAS printf(“C”);

sadkjadsÑKLjdsadkalsdjñlaskjdñaskldjñalS printf(“D”);

askljd ska ids ajdk sdjsakdñad }

Buffer

Consola

A

printf usa el canal stdoutint mi_funcion(int *array, char *array2) { printf(“A”);

asdasdasds adSD SDsd asdas dsad printf(“B”);

ASDHASJDHKJASDHASKJDHAS printf(“C”);

sadkjadsÑKLjdsadkalsdjñlaskjdñaskldjñalS printf(“D”);

askljd ska ids ajdk sdjsakdñad }

Buffer

Consola

A B

printf usa el canal stdoutint mi_funcion(int *array, char *array2) { printf(“A”);

asdasdasds adSD SDsd asdas dsad printf(“B”);

ASDHASJDHKJASDHASKJDHAS printf(“C”);

sadkjadsÑKLjdsadkalsdjñlaskjdñaskldjñalS printf(“D”);

askljd ska ids ajdk sdjsakdñad }

Buffer

Consola

A B

printf usa el canal stdoutint mi_funcion(int *array, char *array2) { printf(“A”);

asdasdasds adSD SDsd asdas dsad printf(“B”);

ASDHASJDHKJASDHASKJDHAS printf(“C”);

sadkjadsÑKLjdsadkalsdjñlaskjdñaskldjñalS printf(“D”);

askljd ska ids ajdk sdjsakdñad }

Buffer

ConsolaAB

printf usa el canal stdoutint mi_funcion(int *array, char *array2) { printf(“A”);

asdasdasds adSD SDsd asdas dsad printf(“B”);

ASDHASJDHKJASDHASKJDHAS printf(“C”);

sadkjadsÑKLjdsadkalsdjñlaskjdñaskldjñalS printf(“D”);

askljd ska ids ajdk sdjsakdñad }

Buffer

ConsolaAB

C

printf usa el canal stdoutint mi_funcion(int *array, char *array2) { printf(“A”);

asdasdasds adSD SDsd asdas dsad printf(“B”);

ASDHASJDHKJASDHASKJDHAS printf(“C”);

sadkjadsÑKLjdsadkalsdjñlaskjdñaskldjñalS printf(“D”);

askljd ska ids ajdk sdjsakdñad }

Buffer

ConsolaAB

C D

printf usa el canal stdoutint mi_funcion(int *array, char *array2) { printf(“A”);

asdasdasds adSD SDsd asdas dsad printf(“B”);

ASDHASJDHKJASDHASKJDHAS printf(“C”);

sadkjadsÑKLjdsadkalsdjñlaskjdñaskldjñalS printf(“D”);

askljd ska ids ajdk sdjsakdñad }

Buffer

ConsolaAB

C D

printf usa el canal stdoutint mi_funcion(int *array, char *array2) { printf(“A”);

asdasdasds adSD SDsd asdas dsad printf(“B”);

ASDHASJDHKJASDHASKJDHAS printf(“C”);

sadkjadsÑKLjdsadkalsdjñlaskjdñaskldjñalS printf(“D”);

askljd ska ids ajdk sdjsakdñad }

Buffer

ConsolaAB

C D

printf usa el canal stdoutint mi_funcion(int *array, char *array2) { printf(“A”);

asdasdasds adSD SDsd asdas dsad printf(“B”);

ASDHASJDHKJASDHASKJDHAS printf(“C”);

sadkjadsÑKLjdsadkalsdjñlaskjdñaskldjñalS printf(“D”);

askljd ska ids ajdk sdjsakdñad }

Buffer

ConsolaABSegmentation fault.

Para depuración se usa el canal stderr

Para depuración se usa el canal stderr

fprintf(stderr, …)

Razones para no usar printf

1) No es una herramienta de depuración2) Nos obliga a ir probando para acotar el fallo

3) Nos puede engañar

Razones para no usar fprintf

1) No es una herramienta de depuración2) Nos obliga a ir probando para acotar el fallo

3) Nos puede engañar

Ahora sí… gdb

#include <stdlib.h> #include <stdio.h>

int main (int argc, char* argv[]) { int *s = NULL; printf("A"); printf("B"); printf("%d", *s); printf("C"); printf("D"); return 0; }

bash$ gcc code.c -o codebash$ ./codeSegmentation fault.bash$

bash$ gcc code.c -o code -g

bash$ gcc code.c -o code -gbash$ ./code

bash$ gcc code.c -o code -gbash$ ./codeSegmentation fault.

bash$ gcc code.c -o code -gbash$ ./codeSegmentation fault.bash$ gdb code

bash$ gcc code.c -o code -gbash$ ./codeSegmentation fault.bash$ gdb code(gdb) runProgram received signal SIGSEGV, Segmentation fault.

bash$ gcc code.c -o code -gbash$ ./codeSegmentation fault.bash$ gdb code(gdb) runProgram received signal SIGSEGV, Segmentation fault.0x08048439 in main (argc=1, argv=0xffffd364) at code.c:9

bash$ gcc code.c -o code -gbash$ ./codeSegmentation fault.bash$ gdb code(gdb) runProgram received signal SIGSEGV, Segmentation fault.0x08048439 in main (argc=1, argv=0xffffd364) at code.c:99 printf("%d", *s);

Órdenes usuales- l, list ! Muestra las líneas de código - b, break ! Crea un breakpoint - d, delete ! Borra un breakpoint - clear ! Borra uno o varios breakpoints - info b ! Muestra la lista de breakpoints - c, continue ! Continúa la ejecución - n, next ! Ejecuta la siguiente línea - s, step ! Como next pero entra en subrutinas - display ! Muestra una expresión por parada - print ! Muestra una expresión - bt, where ! Muestra pila funciones (backtrace) - set ! Asigna un valor a una variable

¿Verdadero o Falso?

Verdadero Falso

int main(int argc, char const *argv[]) { if ( 0.1 + 0.2 == 0.3 ) { puts ("Verdadero"); } else { puts ("Falso"); }

return 0; }

Segmentation Fault Ninguna es correcta

¿Verdadero o Falso?

Falso

int main(int argc, char const *argv[]) { if ( 0.1 + 0.2 == 0.3 ) { puts ("Verdadero"); } else { puts ("Falso"); }

return 0; }

Consejos- Siempre inicializar las variables. SIEMPRE. int i = 0; for (i = 0; i < 10; i++);

- Usar calloc mejor que malloc. int *ptr = (int *) malloc (sizeof(int) * 15); int *ptr = (int ) calloc (15, sizeof(int));

Consejos- Código limpio, máximo 80 caracteres por linea.printf(“%s %s %s”, game->player[1]->score, game->player[1]->highscore, game->player[1]->name);printf(“%s %s %s”, game->player[1]->score, game->player[1]->highscore, game->player[1]->name ); - En las comparaciones, las constantes primeroif (variable = 6) {} // Compila if (6 = variable) {} // No compila if (6 == variable) {} // Correcto

¿Por qué no funciona mi práctica?

Aprende a usar el depurador de C: GDB

by @sgomez