Documente Academic
Documente Profesional
Documente Cultură
Subiect: fazele compil arii programelor C Cuvinte cheie: preprocesor, compilator, linkeditor, modul, modul obiect, header, bibliotec a, sier
executabil
Nivelul tehnic: programator cu 1-2 ani de experient a Cuno stint e necesare: limbajul C, bine
Cuprins
1 Precizare 2 Introducere 3 Premizele scrierii de programe mari 4 Solut ia oferit a de C 5 Compilarea C 6 Preprocesarea 7 Compilarea propriu-zis a 8 Linkeditarea 9 Concluzii 10 Glosar
1 1 2 3 5 6 7 8 10 10
1 Precizare
Vom folosi pe alocuri termenul obiect pentru a denota anumite construct ii ale unui limbaj cum ar variabile, constante, funct ii, metode, obiecte ^
n sensul limbajelor orientate pe obiecte. A nu se confunda aceast a not iune cu cea de obiect din limbajele orientate pe obiecte, pe care nu o folosim niciodat a explicit ^
n acest articol, si al c arei sens ^
l socotim mai restr^
ns. ^ Inc a de la aparit ia sa la ^
nceputul anilor '70 limbajul C s-a impus ca lider de necontestat pentru programarea de sistem. Aceasta din urm a cuprinde o clas a larg a de programe care interact ioneaz a foarte str^
ns cu calculatorul si a c aror performant a o afecteaz a pe a tuturor celorlalte. Un exemplu tipic de astfel de program este sistemul de operare. El este singurul program care | de exemplu | interact ioneaz a cu discul. Toate celelalte programe cer serviciile lui pentru acest scop, prin funct iile de lucru cu siere. De aceea el interact ioneaz a str^
ns cu calculatorul". C are mai multe calit a ti care ^
l fac at^
t de apreciat de c atre programatorii de sistem si nu numai. Una dintre ele, de care ne vom ocupa ^
n parte ^
n acest articol, este suportul pe care ^
l ofer a pentru dezvoltarea de programe mari, eventual lucrate ^
n echip a. Vom vedea c a acest suport este oferit prin ni ste mecanisme extrem de simple, dar a c aror existent a are adesea un impact foarte important asupra limbajului ^
nsu si. S a vedem acum ce condit ii trebuie s a e^
ndeplinite de un limbaj pentru ne permite scrierea unor programe mari. S a numim aceste condit ii premize, si s a urm arim apoi ^
ntruparea lor ^
n cazul C-ului.
2 Introducere
Pentru a putea testa corectitudinea | m acar sintactic a | a ec arui modul, el trebuie s a se poat a compila separat de celelalte. Reamintim c a^
n cursul compil arii toate erorile sintactice sunt depistate iar c^
teodat a si posibile erori conceptuale | de exemplu variabile neinit ializate. Compilarea separat a permite corectarea ec arui modul independent. Avem deci: Pe de alt a parte, modulele f ac^
nd parte dintr-un tot, este de a steptat ca unele obiecte funct ii, proceduri, variabile, etc. dintr-un modul s a se foloseasc a cumva de altele, dintr-un alt modul. Pentru c a modulele se pot compila separat, pentru a face posibil a veri carea corectitudinii sintactice a ec aruia ^
n parte, cumva insu sirile obiectelor dintr-un modul care sunt accesibile si din altele trebuie descrise modulelor utilizator. S a numim un obiect variabil a, funct ie, etc. al unui modul care poate folosit de alte module exportat de modulul c aruia ^
i apart ine. El este, prin simetrie, importat de modulele care ^
l folosesc. Premiza care urmeaz a este necesar a pentru ^
ntret inerea u soar a a informat iilor care trebuie s a e folosite din mai multe locuri: PREMIZA 3 : Declarat iile obiectelor exportate de ecare modul trebuie s a e centralizate str^
nse ^
ntr-un singur loc. Declarat ia este o instruct iune care descrie unele din ^
nsu sirile unui obiect; ea va tratat a mai pe larg mai jos, ^
n contextul limbajului C. Avem apoi:
PREMIZA 4 : Trebuie s a existe o metod a prin care declarat iile unui modul exportator sunt preluate de modulele importatoare.
Pentru a ^
ncheia ne mai trebuie o premiz a. Cineva trebuie s a combine rezultatele compil arilor diferitelor module separate ^
ntr-un singur program care se poate executa :
^ In principiu pentru a obt ine programul am putea avea o nou a compilare a tuturor modulelor ^
mpreun a. ^ Ins a din moment ce ecare modul este probabil deja compilat, ar timp c^
stigat dac a am putea folosi acest lucru. S a observ am c a remarcile din aceast a sect iune sunt practic independente de limbajul considerat. Ele arat a care trebuie s a e calit a tile unui limbaj pentru a u sura scrierea unor programe multimodul.
execut iei programului, cum este de exemplu o variabil a. Cu alte cuvinte macro-urile si tipurile au numai declarat ii si niciodat a de nit ii.
Un exemplu
Pentru a ilustra terminologia s a consider am un program foarte simplu format din dou a siere:
*********************** * fisierul : header.h * *********************** define YES 1 define NO 0 define maxa,b a typedef int NUMAR; NUMAR absNUMAR; extern NUMAR m; b ? a : b
* valoarea absoluta *
********************* * fisierul : main.c * ********************* include "header.h" include stdio.h NUMAR m; NUMAR absNUMAR x if x NUMAR 0 return -x; else return x; static NUMAR n; int mainvoid int y,z; * sarim ceva din program * if max y,z m * mai sarim ceva *
5 Compilarea C
Compilarea este format a din trei faze independente, care sunt realizate de obicei de trei programe distincte, care se execut a unul dup a altul sau ^
n paralel. Exemplele pe care le prezent am sunt pentru dou a tipuri de compilatoare : de sub UNIX practic orice UNIX, testate pentru Linux sau MsDos testate cu BorlandC 2.0.
module c si module module program headere preprocesate obiect executabil | ----------------------------------------------^ - | preprocesare | - | compilare | -- | linkeditare |--| | | propriu-zisa | - | legare | --------------------------------- | --------------biblioteci
Prin anumite opt iuni putem ruga compilatorul s a parcurg a numai unele dintre aceste faze. C^
nd compil am mai multe module, noi d am o singur a comand a, dar aceast a comand a invoc a cele trei faze pentru noi. S a presupunem c a avem un program format din modulul main.c de mai sus si modulul error.c. Sub UNIX putem crea rezultatul cu: 5
cc main.c error.c
Chiar c^
nd compilarea este lansat a din mediul integrat BorlandC prin tasta F9, sau prin Compile Build, ^
n realitate acela si lucru se ^
nt^
mpl a : mediul integrat invoc a pentru noi compilatorul cu o astfel de linie, lu^
nd din project numele sierelor de compilat !. Iat a evolut ia sierelor pentru MsDos BorlandC
preprocesare
,! ,!
main:i error:i
compilare
,! ,!
preprocesare
compilare
= legare ;
,! main:exe
6 Preprocesarea
Preprocesarea este o faz a deosebit de interesant a, c areia intent ion am s a-i acord am un articol special c^
ndva. Acum o vom privi din punctul de vedere care ne intereseaz a. Preprocesorul este de obicei un program separat, care se nume ste cpp C PreProcessor. Numele s au vine de la faptul c a el realizeaz a o procesare ^
nainte pre de compilarea propriu-zis a. Preprocesorul este un program care prelucreaz a texte. El prime ste un text iar rezultatul lui este tot un text. Comparat i-l din acest punct de vedere cu celelalte dou a faze. ^ In principiu preprocesorul parcurge toate textele care-i sunt speci cate de sus ^
n jos, lucr^
nd pe linii, c aut^
nd comenzi pentru el numite directive, pe care le execut a. Comenzile pentru preprocesor ^
ncep cu un semn diez ^
n prima coloan a. Preprocesorul C are trei mari grupe de comenzi:
include define undef if else endif
ifndef
sau UNIX
cc -E main.c main.i lib
7 Compilarea propriu-zis a
Datorit a includerii, sierele preprocesate cont in deja declarat iile obiectelor importate. Apoi ele sunt compilate separat premiza 2. Rezultatul acestei compil ari este ceea ce se nume ste modul obiect object le. Borlandc genereaz a siere cu extensia .obj, compilatoarele din UNIX cu extensia .o. Se obt ine c^
te unul pentru ecare modul C init ial. Ce este un modul sier obiect? Este un amestec de program compilat cod ma sin a si variate ^ informat ii. Tot textul C al modulului a fost compilat ^
n cod ma sin a. Ins a referint ele la simboluri externe din alte module nu au putut satisf acute, pentru c a aceste module sunt compilate separat. De aceea modulul obiect cont ine o list a a simbolurilor nesatisf acute, indic^
nd si locurile unde sunt ^ folosite. In plus mai cont ine si o list a a simbolurilor exportate de modul. De asemenea un modul obiect are o parte cu informat ii numite de relocare. Acestea sunt necesare pentru c a toate salturile din codul compilat sar la ni ste adrese care se vor schimba probabil atunci c^
nd modulul obiect va pus cap la cap cu altele pentru a forma executabilul. 7
Adesea modulul obiect mai cont ine si alte informat ii care sunt necesare pentru depanarea programului rezultat. Aceste informat ii arat a c aror siere surs a si c aror linii C le corespund feluritele instruct iuni din codul ma sin a. C^
teodat a faza de compilare propriu-zis a este format a din dou a p art i independente si f acute de programe separate. O prim a faz a genereaz a un program ^
n limbaj de asamblare, iar a doua faz a asambleaz a programul pentru a obt ine un sier obiect.
module programe in module preprocesate asamblare obiect ---| |------------| |------------| |---|- | compilare |- | asamblare |- | | | | | | | ---| |------------| |------------| |----_________________________ compilare propriu-zisa
BorlandC
bcc -c error.c main.c
Fi sierul obiect nu arat a prea interesant | pentru cititorul uman | dar putet i ^
ncerca s a oprit i compilarea la limbaj de asamblare: UNIX
cc -S error.c main.c
BorlandC
bcc -S error.c main.c
BorlandC
tasm error.c main.c
8 Linkeditarea
Dup a cum am v azut ecare modul surs a este compilat separat ^
ntr-un modul obiect. Modulele obiect au o mult ime de referint e nesatisf acute la obiectele importate. Legarea modulelor implic^
nd completarea referint elor obiectelor globale, relocarea codului este f acut a de ultima faz aa compil arii, numit a linkeditare. Link = leg atur a^
n englez a. Ea este f acut a de programul ld ^
n UNIX sau tlink BorlandC. Argumentele ei sunt module obiect. Interesant este c a aceste module obiect pot obt inute prin compilarea unor programe scrise ^
n limbaje diferite; este frecvent a combinarea programelor scrise ^
n limbaj de asamblare cu a celor ^
n C: toate sunt compilate la module obiect, dup a care sunt legate ^
mpreun a. Lucrurile nu sunt foarte simple, pentru c a trebuie respectate anumite convent ii de exemplu compilatorul C se poate a stepta ca anumit i regi stri s a nu e schimbat i de nici o funct ie. Putet i ^
ncerca s a legat i modulele obiect obt inute mai sus astfel, de si n-o s a mearg a! UNIX :
ld main.o error.o
BorlandC :
tlink main.obj error.obj
Iat a de ce: ^
n realitate c^
nd linkerul este invocat de c atre compilatorul de C deci nu separat, cum am f acut noi mai sus, mai prime ste ca argumente, pe l^
ng a modulele obiect generate prin fazele anterioare ale compil arii si cel put in o bibliotec a. Este vorba de biblioteca standard C, numit a ^
n UNIX libc.a, iar ^
n DOS cs.lib ^
n locul lui s poate o alt a liter a care depinde de modelul de memorie pe care l-at i folosit. Erorile obt inute prin comanda de mai sus arat a care sunt simbolurile externe importate din bibliotec a si care au lipsit la legare. Pentru a lega modulele trebuie speci cate si bibliotecile. Sintaxa la BorlandC pentru linker e put in mai complicat a: BorlandC :
tlink c0s main error, main, ,cs
Fi sierele c0s Borland, respectiv crt0.o UNIX care apar mai sus sunt ni ste module obiect care cont in codul unei funct ii cu care se^
ncepe execut ia programului, care va cheama funct ia main si care dup a executarea acesteia cheam a funct ia exit, pentru a termina civilizat programul. 9
O bibliotec a cs.lib respectiv libc.a sunt biblioteci este de fapt o colect ie de module obiect care au fost compilate mai demult din sursele lor si au fost str^
nse laolalt a^
ntr-un sier arhiv a. ^ In libc.a cs.lib se a a codul funct iilor standard pe care programul dumneavoastr a le poate folosi. De exemplu printf, exit, fopen, scanf. Prin convent ie declarat iile acestor funct ii sunt grupate ^
n siere header puse ^
ntr-un anumit loc ^
n sistemul de siere. Acestea sunt headerele incluse prin directiva include nume_header.h ! De aceste headere este nevoie pentru c a ele cont in declarat ille funct iilor exportate de bibliotec a. S i dumneavoastr a putet i crea biblioteci folosind programul ar ^
n UNIX sau tlib ^
n DOS. Aceste programe manipuleaz a arhive biblioteci ^
n multiple feluri. Bibliotecile pot explorate pentru a vedea ce cont in cu tdump ^
n DOS sau cu nm, ranlib, objdump, etc. sub UNIX. O discut ie acestor utilitare este ^
ns a^
n afara acestui articol. Rezultatul obt inut de la linker este ^
n ne un program executabil sub sistemul de operare pentru care lucreaz a linkerul. Un astfel de sier are ^
ns a o structur a destul de complicat a, folosit a de sistemul de operare pentru dou a scopuri: el cont ine informat ii despre structura ^
ns a si a sierului executabil c^
t de lung e codul, c^
t de lungi sunt datele, sistemul de operare pentru care merge, dac a folose ste biblioteci ^
nc arcate dinamic, eventuale date de relocare, etc. si informat ii de depanare, care sunt folosite c^
nd programul este depanat de ex. cu td = Turbo Debugger ^
n DOS sau cu dbx ^
n UNIX. Aceste informat ii sunt preluate din sierele obiect, dac a existau, si ^
n principiu indic a din ce surse C provin instruct iunile din executabilul nal. Aceste informat ii pot scoase din program, dac a nu mai este nevoie ca el s a e depanat, cu tdstrip DOS sau strip UNIX, pentru a face un executabil mai mic. Dou a cuvinte despre linkeditarea dinamic a. Aceasta este o tehnologie relativ nou a, prezent a ^
n sistemul de operare Windows sub forma sierelor-biblioteci cu extensia .dll Dinamic Linking Libraries. Sub UNIX aceste biblioteci se numesc e dll-uri e Shared Libraries biblioteci comune; numele lor cont ine particula so; exemplu: lib.so.4.1. Ideea este destul de simpl a. Exist ao clas a mare de funct ii care tind s a e prezente ^
n majoritatea programelor. Un exemplu tipic este printf: cam toate programele au ceva de scris. Atunci ^
n loc s a se lege linkeze codul acestor funct ii ^
n ecare program, funct iile sunt ^
nc arcate" ^
n memorie o singur a dat a de sistemul de operare, si apoi legate de toate programele care au nevoie de ele. De aici cele dou a denumiri ale acestor biblioteci: dinamice pentru c a legarea nu mai e o faz a a compil arii, ci chiar a execut arii programului legarea se face c^
nd programul este pornit si comune shared pentru c a pot apart ine mai multor programe diferite simultan!
9 Concluzii
Limbajul C pune la dispozit ie ni ste mecanisme excelente pentru scrierea de programe mari. Aceste mecanisme permit scrierea unui program din mai multe buc a ti, care se pot compila separat. reutilizarea buc a tilor ^
n programe diferite sub forma bibliotecilor. o gestiune relativ simpl a a schimb arilor dintr-un modul datorit a headerelor care grupeaz a declarat iile obiectelor exportate. 10
Cunoa sterea fazelor compil arii este esent ial a pentru scrierea unor programe corecte ^
n C. Dac a un obiect este folosit f ar a a declarat, se obt in erori, sau codul generat este incorect! Vom reveni asupra acestui aspect ^
ntr-un articol despre prototipuri de funct ii. Asta poate da na stere la multe bug-uri misterioase. Este clar c a un modul nu poate sti nimic despre obiectele globale adic a cu legare extern a de nite ^
n alte module p^
n a^
n clipa leg arii. Ori p^
n a la legare anumite informat ii se pierd datorit a compil arii de ex. anumite informat ii de tip. Linker-ul ar putea s a nu depisteze anumite erori de exemplu folosirea unui acela si obiect cu tipuri diferite ^
n module diferite. Lect ia se poate rezuma ^
ntr-o propozit ie : nu folosit i niciodat a^
n C funct ii sau variabile nedeclarate! Putet i folosi sau nu pentru declarat ii headere.
10 Glosar
Acest articol si toate din aceast a serie folosesc o terminologie standard, foarte precis a. Iat a semni cat iile cuvintelor cheie din acest text si numele lor englezesc :
local: un obiect este local unui bloc dac a este vizibil numai ^
n acel bloc. A sa sunt ^
n C argumentele
12