Jump to content

Archived

This topic is now archived and is closed to further replies.

VictorCacciari

[Tutorial] GCC - o básico

Recommended Posts

Boas pessoal!!

 

Outro dia, dando uma olhada no fórum, notei a quantidade de gente que não sabe utilizar um compilador da forma correta. Todo mundo comete erros de sintaxe, esquecemos de colocar ';' no final das instruções, confundimos tipos passados para funções....

 

Mas o compilador não perdoa, e nos diz tudo que está errado no nosso código, em questão de sintaxe.

 

Então decidi tentar ensinar a usar um compilador e um debugger, de uma forma básica.

Quem está no linux, muito provavelmente ja tem as duas ferramentas que utilizarei...

minhas versões:

gcc - 4.2.4
gdb - 6.8

Vamos começar com o compilador...

Eu espero que vocês saibam como compilar um código "na mão", isto é, sem "ctrl+f9" do seu IDE.

Para aqueles qu não sabem, a sintaxe do gcc é:

gcc [opções][arquivos][-o saída (opcional)]

Algumas das opções mais utilizadas:

-Idir --> adiciona um diretório "dir" onde o compilador procurará por #includes

 

-Ldir --> adiciona um diretório "dir" onde o linker procurará por bibliotecas

 

-larquivo --> Adiciona um bilioteca a linkagem (*.a, *.lib, *.so, *.dll...),

se não for uma biblioteca "padrão", deve-se indicar o diretório onde ela se encontra, com -L

Não é preciso escrever o "lib" nem a extensão do arquivo, suponha que você quer incluir a bilbioteca /home/eu/projetos/libteste.so

O seu comando ficaria: gcc -L/home/eu/projetos -lteste

 

-c --> apenas compila os objetos, não efetua a linkagem

 

-g --> compila os objetos em debug mode, adicionando informações que permitem a

utilização de um debugger.

 

-Wopção --> SUA OPÇÃO PREFERIDA!!!, habilita os warnings (avisos) do

compilador, são eles que te avisam onde estão os erros do seu código, te dizem até a

linha... que moleza!

 

Acho que para já está bom.

 

Compilando um código

código: http://codepad.org/eOqb8tH6

 

O que o compilador me disse:

victor@matrix:~/Desktop/tuto$ gcc -Wall -Wextra -g code.c

code.c:13: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘void’

code.c:14: error: expected ‘)’ before ‘*’ token

code.c:15: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token

code.c:16: error: expected ‘)’ before ‘*’ token

code.c:17: error: expected ‘)’ before ‘*’ token

code.c: In function ‘main’:

code.c:22: error: ‘node’ undeclared (first use in this function)

code.c:22: error: (Each undeclared identifier is reported only once

code.c:22: error: for each function it appears in.)

code.c:22: error: ‘list’ undeclared (first use in this function)

code.c:24: warning: implicit declaration of function ‘add_node’

code.c:31: error: expected ‘;’ before ‘add_node’

code.c:34: warning: implicit declaration of function ‘print_list’

code.c:38: warning: implicit declaration of function ‘remove_node’

code.c:38: warning: implicit declaration of function ‘find_node’

code.c:45: warning: implicit declaration of function ‘destroy_list’

code.c: At top level:

code.c:53: error: expected ‘)’ before ‘*’ token

code.c:75: error: expected ‘)’ before ‘*’ token

code.c:105: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token

code.c:122: error: expected ‘)’ before ‘*’ token

code.c:135: error: expected ‘)’ before ‘*’ token

Notem nas opções que utilizei para compilar o código:

-Wall: dizendo o compilador para mostrar TODOS os warnings

-Wextra: pedindo ainda os warnings extra

-g: debug mode.

 

E notem que o compilador me falou TUDO que estava errado no código...

A nomenclatura é muito simples:

 

<nome_do_arquivo>:<número_da_linha>:<error ou warning>: o que você fez de errado

 

Depois de seguir as mensagens dele, temos outro código:

http://codepad.org/tlQGsL0t

 

Ao compilar esse novo código.... tcharaaaam! nenhum erro, nem warning! maravilha!!

 

Mas e ao executar o programa?

victor@matrix:~/Desktop/tuto$ ./a.out

[804a008] 1

[804a018] 2

[804a028] 3

[804a038] 4

[804a048] 5

[804a058] 6

[804a068] 7

[804a078] 8

[804a088] 9

 

Vamos agora apagar alguns nós (7 e 8)...

 

[804a008] 1

[804a018] 2

[804a028] 3

[804a038] 4

[804a048] 5

[804a058] 6

[804a088] 9

 

Vamos liberar a lista inteira...

 

Segmentation fault

OooOOooOOoops... SIGSEGV...

É Agora que entra o nosso amigo gdb

 

Entre amanhã e depois escrevo qualquer coisinha sobre como debugar algo no modo texto!

Abraços, até a próxima!!

 

ps.: Espero que a quantidade de tópicos inúteis diminua, e apareçam mais tópicos interessantes e que tem algo a acrescentar para todo o fórum. http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

Share this post


Link to post
Share on other sites

Só complementando o post do Vitor.

 

 

-o : Permite que você mude o nome do arquivo de saída, não somente o nome do arquivo executável.

 

@file : Lê as opções pasadas p/ o compilador a partir de um arquivo texto, sendo que as opções devem ser separadas por espaço.

 

-std= : Permite escolher o padrão p/ compilar a linguagem.

 

-fmessage-length=n : Permite modificar o tamanho máximo das mensagens exibidas pelo compilador.

 

-fsyntax-only : Apenas verifica se o código não possui erros de sintaxe.

 

-Wfatal-errors : O processo de compilação é interrompido no primeiro erro encontrado, não processando o restante do fonte.

 

-Wconversion : Avisa sobre conversões implícitas que podem alterar um valor. Exemplo de código:

 

#include <stdlib.h>
int main (int argc, char *argv[])
{
abs(34.65);
return 0.345;
}

 

-Wshadow : Avisa se variáveis locais 'sobrescrevem' declarações globais. Exemplo de código:

 

#include <stdio.h>

int b = 4;
int main (int argc, char *argv[])
{
int b = -1;
printf("b=%d\n",b);
}

 

 

-Wuninitialized : Para utilizar esta opção é necessário passar a opção -O. As opções -Wall e -Wextra habilitam uninitialized.

 

 

-fstack-protector, -fstack-protector-all e -Wstack-protector: Ao invés de se ter uma mensagem de falha de segmentação, temos um backtrace.

O fstack-protector adiciona código p/ verificar estouro de buffer para as funções que chamam alloca ou que possuam buffers maiores que 8 bytes.

 

 

#include <stdio.h>

int main (int argc, char *argv[])
{
char s[7];
gets(s);
return 0;
}

 

isis@linux-gy11:~/Imasters> gcc std-exemplo.c -fstack-protector -Wstack-protector

std-exemplo.c: In function ‘main’:

std-exemplo.c:4: warning: not protecting function: no buffer at least 8 bytes long

/tmp/ccqFAa6W.o: In function `main':

std-exemplo.c:(.text+0x18): warning: the `gets' function is dangerous and should not be used.

 

Trocando o tamanho do array para 8:

 

isis@linux-gy11:~/Imasters> gcc std-exemplo.c -fstack-protector -Wstack-protector

/tmp/ccaliVq7.o: In function `main':

std-exemplo.c:(.text+0x29): warning: the `gets' function is dangerous and should not be used.

 

A saída da execução do programa com essas opções é:

 

isis@linux-gy11:~/Imasters> ./a.out

qwerttyasdfgzxcvbb

*** stack smashing detected ***: ./a.out terminated

======= Backtrace: =========

/lib/libc.so.6(__fortify_fail+0x48)[0xb803ddb8]

/lib/libc.so.6(__fortify_fail+0x0)[0xb803dd70]

./a.out[0x80484b7]

/lib/libc.so.6(__libc_start_main+0xe5)[0xb7f6d705]

======= Memory map: ========

08048000-08049000 r-xp 00000000 08:12 137968 /home/isis/Imasters/a.out

08049000-0804a000 r--p 00000000 08:12 137968 /home/isis/Imasters/a.out

0804a000-0804b000 rw-p 00001000 08:12 137968 /home/isis/Imasters/a.out

0804b000-0806c000 rw-p 0804b000 00:00 0 [heap]

b7f56000-b7f57000 rw-p b7f56000 00:00 0

b7f57000-b80ac000 r-xp 00000000 08:12 1338 /lib/libc-2.9.so

b80ac000-b80ad000 ---p 00155000 08:12 1338 /lib/libc-2.9.so

b80ad000-b80af000 r--p 00155000 08:12 1338 /lib/libc-2.9.so

b80af000-b80b0000 rw-p 00157000 08:12 1338 /lib/libc-2.9.so

b80b0000-b80b4000 rw-p b80b0000 00:00 0

b80b4000-b80c1000 r-xp 00000000 08:12 91475 /lib/libgcc_s.so.1

b80c1000-b80c2000 r--p 0000c000 08:12 91475 /lib/libgcc_s.so.1

b80c2000-b80c3000 rw-p 0000d000 08:12 91475 /lib/libgcc_s.so.1

b80c3000-b80c4000 rw-p b80c3000 00:00 0

b80c4000-b80e2000 r-xp 00000000 08:12 483 /lib/ld-2.9.so

b80e2000-b80e3000 r--p 0001d000 08:12 483 /lib/ld-2.9.so

b80e3000-b80e4000 rw-p 0001e000 08:12 483 /lib/ld-2.9.so

bfbce000-bfbe3000 rw-p bffeb000 00:00 0 [stack]

ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]

Abortado

 

A opção fstack-protect-all não possui limite de bytes.

 

 

-glevel : As opções -g e -ggdb para o GDB não torna disponível informações sobre defines. Para ser possível dar um print ou display em defines deve ser especificada a opção -g3.

 

-pg : Cria código extra p/ que se possa usar o GNU profiler.

 

 

-fprofile-arcs : Podemos utilizar esta opção em conjunto com o comando gcov p/ verificar quantas vezes cada linha do programa foi executada.Exemplo:

 

#include <stdio.h>
float fibrec(float a) {
if (a==1 || !a)
	return 1;
return fibrec(a-1)+fibrec(a-2);
if (a < 0) print("negativo\n");
}


int main (int argc, char *argv[])
{
printf("F(20)=%.0f\n", fibrec(20));
}

 

isis@linux-gy11:~/Imasters> gcc std-exemplo.c -fprofile-arcs

isis@linux-gy11:~/Imasters> gcov std-exemplo.c

std-exemplo.gcda:cannot open data file, assuming not executed

File 'std-exemplo.c'

Lines executed:0.00% of 7

std-exemplo.c:creating 'std-exemplo.c.gcov'

 

isis@linux-gy11:~/Imasters> cat std-exemplo.c.gcov

-: 0:Source:std-exemplo.c

-: 0:Graph:std-exemplo.gcno

-: 0:Data:-

-: 0:Runs:0

-: 0:Programs:0

-: 1:#include <stdio.h>

#####: 2:float fibrec(float a) {

#####: 3: if (a==1 || !a)

#####: 4: return 1;

#####: 5: return fibrec(a-1)+fibrec(a-2);

-: 6: if (a < 0) print("negativo\n");

-: 7:}

-: 8:

-: 9:

-: 10:int main (int argc, char *argv[])

#####: 11:{

#####: 12: printf("F(20)=%.0f\n", fibrec(20));

#####: 13:}

-: 14:

 

As linhas que estão com '#' não foram executadas, já que não executamos o programa. Após executar o programa, temos

 

isis@linux-gy11:~/Imasters> gcov std-exemplo.c

File 'std-exemplo.c'

Lines executed:100.00% of 7

std-exemplo.c:creating 'std-exemplo.c.gcov'

 

isis@linux-gy11:~/Imasters> cat std-exemplo.c.gcov

-: 0:Source:std-exemplo.c

-: 0:Graph:std-exemplo.gcno

-: 0:Data:std-exemplo.gcda

-: 0:Runs:1

-: 0:Programs:1

-: 1:#include <stdio.h>

21891: 2:float fibrec(float a) {

21891: 3: if (a==1 || !a)

10946: 4: return 1;

10945: 5: return fibrec(a-1)+fibrec(a-2);

-: 6: if (a < 0) print("negativo\n");

-: 7:}

-: 8:

-: 9:

-: 10:int main (int argc, char *argv[])

1: 11:{

1: 12: printf("F(20)=%.0f\n", fibrec(20));

1: 13:}

-: 14:

Share this post


Link to post
Share on other sites

×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.