Considere o programa formado pelos dois arquivos abaixo:
arquivo temp1.c
:
#include <stdio.h> int a = 1024; int main (void) { foo(); printf("%d\n", a); return 0; }
arquivo temp2.c
:
extern char a; int b = 10; void foo (void) { a = -3; }
> gcc -c -Wall temp1.c > gcc -c -Wall temp2.c > gcc -o prog temp1.o temp2.o(Você poderia fazer tudo de uma só vez chamando
gcc -Wall temp1.c temp2.c
,
mas aí o gcc
não gera os arquivos .o
.)
Explique a saída do programa.
Use o programa nm
para inspecionar os símbolos
usados por cada módulo
(chame nm temp1.o
e nm temp2.o
).
Você consegue inferir o significado das letras que aparecem
na saída deste programa (U
, T
, etc.)?
(Dica: google "man nm".)
Se no 2o arquivo trocarmos a linha extern char a;
por char a = 0;
, o que acontece?
Como o erro foi detectado?
E se a troca for por static char a = 0;
,
o que acontece?
Certifique-se que você entendeu o que aconteceu!
O que acontece se no 2o arquivo definirmos a função
foo
como static
?
Certifique-se que você entendeu o que aconteceu!
De volta aos arquivos originais,
o que ocorre se trocarmos, no 1o arquivo,
a linha foo();
por b();
?
Repita com o valor inicial de b
sendo 0xC3,
ao invés de 0 (Atenção: Gere o executável com
gcc -o prog -Wa,--execstack temp1.c temp2.c
)
.
Certifique-se que você entendeu o que aconteceu nos dois casos!
Escreva dois arquivos temp1.h
e temp2.h
,
a serem incluídos tanto por
temp1.c
quanto por temp2.c
,
que evitem os problemas que criamos nos itens anteriores.
("Evitar os problemas" significa que, ao invés de erros de execução
sem sentido, teremos erros de compilação mais bem documentados se
fizermos algo errado.)
Refaça os erros anteriores e descreva o que ocorre agora que
temos os .h
.