set
21
2009

Básico de ponteiros com o GDB

Esse é um pequeno lembrete para quem quer pegar o conceito de ponteiro rápido. É tão simples que nem programa direito você vai precisar, só seguir sua intuição e o GDB ;-)

1. Básico

Vamos começar com um código muito simples.

#include <stdio.h>
int main(int argc, char *argv[]) {
int *ptr = NULL;
int variavel_A;
int variavel_B;
variavel_A = 5;
variavel_B = 18;
return 0;
}

Usar o menor comando do GCC para compilar e linkar o programa. A saída (o executável) chamará a.out, se você quiser outro nome adicione “-o <nome>” no final do comando.

gcc -ggdb basico.c

E iniciar o depurador, lembre-se que o texto em (vermelho) é comentário e negrito é um comando para você digiar na CLI (command-line interface) do GDB.

maluta@coding ~ $ gdb -q a.out
(gdb) l (lista o código)
1 #include <stdio.h>
2
3
4 int main(int argc, char *argv[]) {
5
6 int *ptr = NULL;
7 int variavel_A;
8 int variavel_B;
9
10 variavel_A = 5;
(gdb)
11 variavel_B = 18;
12
13 return 0;
14
15 }
(gdb) break 13 (inserir um breakpoint na linha 13)
Breakpoint 1 at 0x80483c6: file basico.c, line 13.

(gdb) r (run - inicia o programa)
Starting program: /home/maluta/a.out
Breakpoint 1, main () at basico.c:13
13 return 0;
(Mostra o que tem na variavel_A)
(gdb) print variavel_A
$1 = 5


(Mostra o que tem na variavel_B)
(gdb) print variavel_B
$2 = 18
(Imprime o conteúdo do endereço definido em ptr)
(gdb) print *ptr
Cannot access memory at address 0x0 (ooops... essa não é uma posição válida!)
(gdb) print ptr (mas é claro que ptr guarda um valor...)
$3 = (int *) 0x0 (que é NULL)


(E qual o endereço da variável_A?)
(gdb) print &variavel_A
$4 = (int *) 0xbfbc0ddc
(gdb) print *variavel_A (Podemos ver que não conseguimos acessar a variavel_A como um ponteiro pois ela guarda um endereço inválido)
Cannot access memory at address 0x5


(O endereço da variável_B)
(gdb) print &variavel_B
$5 = (int *) 0xbfbc0de0
(Vamos fazer ptr apontar para a variavel_A)
(gdb) set ptr=0xbfbc0ddc
(gdb) print *ptr (e mostrar o seu conteúdo)
$6 = 5
(Vamos fazer ptr apontar para a variavel_B)
(gdb) set ptr=&variavel_B
(gdb) print *ptr
$7 = 18
(gdb)

2. Intermediário

Vamos dar mais um passo.

#include 
#include  /* malloc() */
#include  /* strncpy */
int main(int argc, char *argv[]) {
 
        char *nome;
 
        nome = malloc(10*sizeof(char));
        strncpy(nome,"tiago",5);
        return 0;
}

maluta@coding ~ $ gdb -q a.out
(gdb) l
1 #include <stdio.h>
2 #include <stdlib.h> /* malloc() */
3 #include <string.h> /* strncpy */
4 int main(int argc, char *argv[]) {
5
6
7 char *nome;
8
9 nome = malloc(10*sizeof(char));
10
(gdb) break 9
Breakpoint 1 at 0x8048421: file intermediario.c, line 9.
(gdb) r
Starting program: /home/maluta/a.out
Breakpoint 1, main () at basico.c:9
9 nome = malloc(10*sizeof(char));
(gdb) print nome
$1 = 0xb80b1190 "U\211åWVSèÀ\207" (LIXO)
(gdb) n (next - executa a próxima instrução)
11 strncpy(nome,"tiago",5);
(gdb) n
15 return 0;
(gdb) print nome (texto copiado)
$2 = 0x804b008 "tiago"
(gdb) x/5x nome (conteudo em hexa)
0x804b008: 0x74 0x69 0x61 0x67 0x6f
(gdb) x/5c nome (conteudo em ascii)
0x804b008: 116 't' 105 'i' 97 'a' 103 'g' 111 'o'
(Vamos mudar a primeira letra da string)
(gdb) set {char}nome='T'
(gdb) x/5x nome
0x804b008: 0x54 0x69 0x61 0x67 0x6f
(gdb) x/5c nome
0x804b008: 84 'T' 105 'i' 97 'a' 103 'g' 111 'o'
(Vamos colocar um espaço em branco na segunda posição)
(gdb) set {char}(nome+1)=' ' (lembre-se que o índice começa em zero)
(gdb) print nome
$11 = 0x804b008 "T ago"
(gdb) x/5x nome
0x804b008: 0x54 0x20 0x61 0x67 0x6f
(gdb) x/5c nome
0x804b008: 84 'T' 32 ' ' 97 'a' 103 'g' 111 'o'
(Você pode ver o conteúdo da variável com deslocamento 'offset')
(gdb) print nome+3
$17 = 0x804b00b "go"

Meu amigo Antônio (aka John) fez um exemplo do uso de classes em C, vamos utilizá-lo por aqui. Para mostrar o ponteiro para função, só vou adicionar uma função/método subtraiMinhaClasse no código.

#include 
 
struct MinhaClasse{
    int a;
    int b;
    int (*soma)();
};
 
int somaMinhaClasse(struct MinhaClasse *this){
    return (*this).a + (*this).b;
}
 
int subtraiMinhaClasse(struct MinhaClasse *this){
    return (*this).a - (*this).b;
}
 
void construtorMinhaClasse(struct MinhaClasse *this){
    this-&gt;soma = somaMinhaClasse;
}
 
int main(){
 
    int resposta;
    struct MinhaClasse objeto;
    construtorMinhaClasse(&amp;objeto);
 
    objeto.a = 33;
    objeto.b = 15;
 
    resposta = objeto.soma();
 
    printf("%i",resposta);
 
return 0;
}

(gdb) break 34

Breakpoint 1 at 0x8048425: file john.c, line 34.

(gdb) r

Starting program: /home/maluta/a.out

Breakpoint 1, main () at john.c:34

29 printf("%i",resposta);


(Vamos ver o que tem na struct)

(gdb) print objeto

$1 = {a = 33, b = 15, soma = 0x80483d0 <somaMinhaClasse>}


(Bem como o valor contido em resposta)

(gdb) print resposta

$2 = 48


(Qual o endereço da função somaMinhaClasse?)

(gdb) print somaMinhaClasse

$3 = {int (struct MinhaClasse *)} 0x80483d0 <somaMinhaClasse>

(Que interessante... objeto.soma e somaMinhaClasse tem o mesmo endereço?)

(gdb) print objeto.soma

$4 = (int (*)()) 0x80483d0 <somaMinhaClasse>

(E a função subtraiMinha classe está sozinha?)

(gdb) print subtraiMinhaClasse

$5 = {int (struct MinhaClasse *)} 0x80483e3 <subtraiMinhaClasse>


(Que tal conectá-la a alguém?)

(gdb) set objeto.soma=subtraiMinhaClasse

(E lógico ver o resultado!)

(gdb) print objeto.soma()

$6 = 18

(O novo par de objeto.soma ;-) )

(gdb) print objeto.soma

$8 = (int (*)()) 0x80483e3 <subtraiMinhaClasse>


(Não gostei! Quero voltar para o que tinha antes)

(gdb) set objeto.soma=somaMinhaClasse

(gdb) print objeto.soma()

$9 = 48

tags: ,
posted in programação by Tiago Maluta

Follow comments via the RSS Feed | Deixe um comentário | Trackback URL

Leave Your Comment