Considere o programa formado pelos arquivos abaixo:
arquivo temp1.c
:
#include <stdio.h> #include "temp1.h" #include "temp2.h" int a = 1024; int main (void) { foo(); printf("%d\n", a); return 0; }
arquivo temp2.c
:
#include "temp1.h" #include "temp2.h" int b = 10; void foo (void) { a = -3; }
arquivo temp1.h
:
extern int a;
arquivo temp2.h
:
extern int b; void foo(void);
Note que os arquivos temp1.h
e temp2.h
contém declarações dos simbolos globais exportados, respectivamente,
por temp1.c
e temp2.c
A inclusão desses arquivos garante a consistência dessas declarações entre os
módulos, tanto para os arquivos que definem os símbolos quanto para os que
os importam.
> 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, neste caso, o gcc
não gera os arquivos .o
.)
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: "man nm".)
Troque no 1o arquivo (temp1.c
) a linha int a = 1024;
por char a = 1;
e recompile esse módulo.
O que acontece? Em que passo foi detetado o erro? (compilação? linkedição?)
Restabeleça no arquivo temp1.c
declaração int a = 1024;
temp2.c
) a linha #include "temp1.h"
por extern char a;
Recompile os dois módulos, gere um novo executável e execute o programa. O que aconteceu? Você consegue explicar?
temp2.c
a declaração
extern char a;
por int a = 1;
e recompile este módulo.
Tente gerar um novo executável. O que acontece agora? Algum erro ocorreu?
(se sim, em um passo?)
Inspecione novamente os símbolos dos módulos objeto usando o nm
.
static int a = 1;
,
o que acontece? Por que?
Restaure a inclusão de "temp1.h"
no 2o arquivo (temp2.c
),
e remova a declaração static int a = 1;
.
temp1.c
) a linha #include "temp2.h"
(isto é, a declaração dos símbolos exportados por temp2).
Troque em temp1.c
a linha foo();
por b();
Recompile os dois módulos e gere um novo executável com
gcc -Wa,--execstack -Wall -c temp1.c gcc -Wa,--execstack -Wall -c temp2.c gcc -o prog -Wa,--execstack temp1.o temp2.oVerifique com o
nm
as tabelas de símbolo de cada módulo
(em especial, o símbolo b
).
Execute o programa. O que aconteceu? Por que?
b
em temp2.c
por 0xC3. Recompile este módulo, gere um novo executável, e execute-o.
O que acontece agora? Por que?