This shows you the differences between two versions of the page.
uso:laboratoare:new:04-appdev:concepts [2018/10/24 04:00] diana_sorina.grecu |
uso:laboratoare:new:04-appdev:concepts [2019/10/22 10:59] (current) adrian.zatreanu [Scrierea și compilarea codului sursa] |
||
---|---|---|---|
Line 5: | Line 5: | ||
Toate dispozitivele electronice pe care le folosim în viața de zi cu zi, de la | Toate dispozitivele electronice pe care le folosim în viața de zi cu zi, de la | ||
latopuri sau calculatoare personale, până la telefoane mobile sau smart watch-uri, | latopuri sau calculatoare personale, până la telefoane mobile sau smart watch-uri, | ||
- | toate au în comun un lucru: rulează software. Având în vedere cât de variate | + | toate au în comun un lucru: rulează **software**. Având în vedere cât de variate |
sunt sistemele pe care rulează aplicațiile, este important să se cunoască principalii | sunt sistemele pe care rulează aplicațiile, este important să se cunoască principalii | ||
factori care influențează deciziile luate în vederea creării uneia. | factori care influențează deciziile luate în vederea creării uneia. | ||
Line 24: | Line 24: | ||
Bazat pe modul în care codul de nivel înalt este transformat și rulat pe procesor, | Bazat pe modul în care codul de nivel înalt este transformat și rulat pe procesor, | ||
- | putem clasifica limbajele de programare în limbaje compilate sau interpretate. | + | putem clasifica limbajele de programare în două categorii: |
- | Diferența între cele două este că pentru a rula un limbaj compilat, acesta este | + | * limbaje **compilate** |
- | întâi transformat în limbaj mașină, rezultând un fișier executabil, care apoi poate | + | * limbaje **interpretate** |
- | fi rulat oricând. Pe de altă parte, un limbaj interpretat este executat direct, prin | + | * limbaje **hibride** |
- | intermediul unui interpretor. Interpretorul este cel care ia fiecare instrucțiune, o | + | |
- | transformă în cod mașină iar aceasta este executată imediat. | + | Fiecare tip de limbaj vine cu propriile avantaje și dezavantaje. Limbajele compilate |
+ | sunt mai stricte, deci există șanse mai mici să greșesti, dar au | ||
+ | dezavantajul că nu sunt [[https://www.techopedia.com/definition/8921/portability|portabile]]. | ||
+ | În cazul limbajelor compilate codul sursă este întâi transformat în limbaj mașină, | ||
+ | rezultând un fișier executabil, care apoi poate fi rulat oricând. | ||
+ | Codul sursă scris într-un limbaj interpretat este executat direct, prin intermediul | ||
+ | unui interpretor. Interpretorul este cel care ia fiecare instrucțiune, o transformă | ||
+ | în cod mașină iar aceasta este executată imediat. Limbajele interpretate sunt portabile, | ||
+ | însă greșelile de programare pot fi văzute doar în timpul rulării, niciodată de dinainte. | ||
În funcție de scopul aplicației noastre, trebuie să știm să alegem limbajul de | În funcție de scopul aplicației noastre, trebuie să știm să alegem limbajul de | ||
- | programare adecvat; de exemplu, limbajele compilate (precum C/C++) au avantajul | + | programare adecvat. De exemplu, limbajele compilate (precum C/C++) au avantajul |
timpului de execuție mai rapid, pe când cele interpretate (PHP/Perl) au mai multă | timpului de execuție mai rapid, pe când cele interpretate (PHP/Perl) au mai multă | ||
portabilitate, interpretorul fiind cel care transformă codul sursă în cod mașină | portabilitate, interpretorul fiind cel care transformă codul sursă în cod mașină | ||
specific procesorului. | specific procesorului. | ||
- | Există și o a treia categorie de limbaje și anume limbajele hibride, care încapsulează | + | A treia categorie de limbaje și anume limbajele hibride, sunt cele care încapsulează |
elemente de compilare cu elemente de interpretare. | elemente de compilare cu elemente de interpretare. | ||
Pentru că principalul dezavantaj al programelor interpretate este timpul mare de execuție, | Pentru că principalul dezavantaj al programelor interpretate este timpul mare de execuție, | ||
Line 47: | Line 55: | ||
din bytecode și le transformă în cod mașină. Putem deci considera că avem două etape | din bytecode și le transformă în cod mașină. Putem deci considera că avem două etape | ||
în procesul de rulare: compilare către bytecode și apoi interpretare. | în procesul de rulare: compilare către bytecode și apoi interpretare. | ||
- | Un astfel de limbaj este Python/Java/C#. | + | Exemple de astfel de limbaje sunt Python/Java/C#. |
- | ==== Scrierea si compilarea codului sursa ==== | + | ==== Scrierea și compilarea codului sursa ==== |
=== Scrierea codului === | === Scrierea codului === | ||
Line 78: | Line 86: | ||
- Link-editare: "leagă" între ele mai multe fișiere obiect și creează fișierul executabil. | - Link-editare: "leagă" între ele mai multe fișiere obiect și creează fișierul executabil. | ||
- | <note> | + | <note> |
- | Secțiunea următoare se referă la dezvoltarea în C/C++, acestea fiind limbajele | + | Secțiunea următoare se referă la dezvoltarea în C/C++, acestea fiind limbajele |
- | pe care le veți utiliza și în cadrul cursurilor din facultate. | + | pe care le veți utiliza cel mai mult pentru cursurile din facultate. |
- | </note> | + | </note> |
- | Compilatorul cel mai folosit pentru C/C++ este gcc/g++. | + | Compilatorul cel mai folosit pentru C/C++ este **gcc/g++**. |
- | La simpla rulare a comenzii gcc, se trece prin toate etapele menționate, | + | La simpla rulare a comenzii gcc, se trece prin toate etapele menționate, |
- | obținându-se la final executabilul, însă există opțiuni pentru a întrerupe procesul | + | obținându-se la final executabilul, însă există opțiuni pentru a întrerupe procesul |
- | după un anumit pas al compilării. (man gcc) | + | după un anumit pas al compilării. |
+ | |||
+ | <note> | ||
+ | Pentru a vedea rapid ce opțiuni pune gcc la dispoziție, puteți consulta pagina de manual al | ||
+ | acestuia. Pentru a face asta, rulați comanda ''man gcc''. | ||
+ | </note> | ||
- | De exemplu, următoarea comandă va genera executabilul ''main''. | + | Să prespunem că avem un fișier ''main.c'' ce conține cod C (corect). Următoarea comandă va |
+ | genera executabilul ''main''. | ||
<code bash> | <code bash> | ||
Line 96: | Line 110: | ||
La fiecare modificare adusă programului sursă, toate comenzile de compilare trebuie | La fiecare modificare adusă programului sursă, toate comenzile de compilare trebuie | ||
rulate din nou, lucru ce poate să devină obositor/problematic atunci când este | rulate din nou, lucru ce poate să devină obositor/problematic atunci când este | ||
- | vorba de un proiect complex. Astfel, au apărut makefile-urile, fișiere care | + | vorba de un proiect complex. Astfel, au apărut fișierele ''Makefile'', fișiere care |
conțin aceste comenzi și le pot rula pe toate printr-un singur apel. | conțin aceste comenzi și le pot rula pe toate printr-un singur apel. | ||
- | În concluzie, scopul makefile-urilor este de a automatiza procesul de compilare. | + | În concluzie, scopul acestor fișiere este de a automatiza procesul de compilare. |
<note> | <note> | ||
- | Mai multe informații despre makefile-uri vor fi prezentate în secțiunea ''Demo''. | + | Mai multe informații despre fișiere ''Makefile'' vor fi prezentate în secțiunile următoare. |
</note> | </note> | ||
Line 110: | Line 124: | ||
De cele mai multe ori vă veți lovi de warning-uri sau erori de compilare, iar atunci | De cele mai multe ori vă veți lovi de warning-uri sau erori de compilare, iar atunci | ||
când reușiți să le rezolvați pe acestea, șirul nefericit al evenimentelor va continuă | când reușiți să le rezolvați pe acestea, șirul nefericit al evenimentelor va continuă | ||
- | și veți obține rezultate eronate, segfault-uri etc. | + | și veți obține rezultate eronate sau și mai rău, erori de rulare (ex: [[https://stackoverflow.com/questions/2346806/what-is-a-segmentation-fault|Segmentation fault]]). |
Este important să fim conștienți că o mare parte din timpul dezvoltării unei aplicații | Este important să fim conștienți că o mare parte din timpul dezvoltării unei aplicații | ||
va fi dedicată depanării programului, de aceea este important să fim eficienți în | va fi dedicată depanării programului, de aceea este important să fim eficienți în | ||
Line 120: | Line 134: | ||
Aceasta este cea mai ușoară și intuitivă metodă, însă pentru un program cu sute/mii | Aceasta este cea mai ușoară și intuitivă metodă, însă pentru un program cu sute/mii | ||
de linii de cod este foarte ineficientă. | de linii de cod este foarte ineficientă. | ||
- | Astfel au apărut debugger-ele, programe speciale cu o varietate de funcționalități; | + | Astfel au apărut **debuggerele**, programe speciale cu o varietate de funcționalități; |
* îți permit să oprești programul în anumite puncte ale execuției și să analizezi valorile variabilelor. | * îți permit să oprești programul în anumite puncte ale execuției și să analizezi valorile variabilelor. | ||
* rularea programului pas cu pas | * rularea programului pas cu pas | ||
* modificarea stării programului în timpul rulării | * modificarea stării programului în timpul rulării | ||
- | Unul dintre cele mai cunoscute utilitare pentru depanare este ''gdb''; el suportă | + | Unul dintre cele mai cunoscute utilitare pentru depanare este ''gdb''. El suportă |
- | toate operațiile menționate mai sus. (pentru o mai bună vizulizare a informației | + | toate operațiile menționate mai sus. |
- | folosiți gdb-peda) | + | |
- | Good practice este să nu scrieți blocuri mari de cod fără a le verifica pe parcurs; | + | Good practice este să nu scrieți blocuri mari de cod fără a le verifica pe parcurs. |
- | testați funcționarea corectă a programului pe parcursul dezvoltării acestuia, altfel | + | Testați funcționarea corectă a programului pe parcursul dezvoltării acestuia, altfel |
vă va fi mult mai dificil să detetctați erorile. | vă va fi mult mai dificil să detetctați erorile. | ||
Line 141: | Line 154: | ||
timp cine ce modificări a adus programului. | timp cine ce modificări a adus programului. | ||
- | Gît este un sistem de management și versionare a codului sursă care permite această | + | **Git** este un sistem de management și versionare a codului sursă care permite această |
partajare dorită. Proiectul este stocat într-un repository. Repository-ul conține | partajare dorită. Proiectul este stocat într-un repository. Repository-ul conține | ||
fișierele efective ale proiectului și informații despre acesta. | fișierele efective ale proiectului și informații despre acesta. | ||
Line 148: | Line 161: | ||
Operațiile de bază ce pot fi efectuate asupra unui repository sunt: | Operațiile de bază ce pot fi efectuate asupra unui repository sunt: | ||
- | * init: pentru a inițializa un repo de git local. | + | * init: inițializează un repository de git local. |
- | * clone: se copiază local întreg repository-ul; practic se creează pe sistemul vostru un director cu toate fișierele puse online la momentul clonării. | + | * clone: copiază local un întreg repository deja existent; practic se creează pe sistemul vostru un director cu toate fișierele puse online la momentul clonării. |
- | * commit:se salvează toate modificările aduse proiectului; starea actuală este salvată local. Dacă modificările nu sunt făcute publice, atunci ceilalți colaboratori nu le vor putea vedea. | + | * commit: salvează toate modificările aduse proiectului; starea actuală este salvată local. Dacă modificările nu sunt făcute publice, atunci ceilalți colaboratori nu le vor putea vedea. |
- | * push: pentru publicarea modificărilor salvate prin commit. | + | * push: publică modificările salvate prin commit. |
- | * pull: se descarcă local ultimele modificări aduse de colaboratori în cadrul proiectului. | + | * pull: descarcă local ultimele modificări aduse de colaboratori în cadrul proiectului. |
+ | <note> | ||
+ | Mai multe detaliu despre operațiile git veți afla în secțiunile următoare. | ||
+ | </note> | ||
+ | |||
====Biblioteci===== | ====Biblioteci===== | ||
+ | |||
+ | <note> | ||
+ | Termenii de ''librărie'' și ''bibliotecă'' **NU** sunt interschimbabili. | ||
+ | </note> | ||
O bibliotecă este o colecție de funcții precompilate. În momentul în care un program are nevoie de o funcție neinclusă în fișiere sursă proprii, linker-ul va apela respectiva funcție din bibliotecă. Numele fișierului reprezentând biblioteca trebuie să aibă prefixul **lib**: | O bibliotecă este o colecție de funcții precompilate. În momentul în care un program are nevoie de o funcție neinclusă în fișiere sursă proprii, linker-ul va apela respectiva funcție din bibliotecă. Numele fișierului reprezentând biblioteca trebuie să aibă prefixul **lib**: | ||
<code bash> | <code bash> | ||
- | student@uso:~$ ls -l /usr/lib/libm.* | + | student@midgard$ ls -l /usr/lib/libm.* |
-rw-r--r-- 1 root root 496218 2010-01-03 15:19 /usr/lib/libm.a | -rw-r--r-- 1 root root 496218 2010-01-03 15:19 /usr/lib/libm.a | ||
lrwxrwxrwx 1 root root 14 2010-01-14 12:17 /usr/lib/libm.so -> /lib/libm.so.6 | lrwxrwxrwx 1 root root 14 2010-01-14 12:17 /usr/lib/libm.so -> /lib/libm.so.6 | ||
Line 168: | Line 189: | ||
* **partajate** - au extensia ''.so'' sub Linux (''.dll'' în Windows) | * **partajate** - au extensia ''.so'' sub Linux (''.dll'' în Windows) | ||
- | Pentru a putea lega un program cu o bibliotecă, aceasta trebuie să fie prezentă în sistem. Pe sistemele Linux (și nu numai) sunt două modalități de a realizarea legarea unei biblioteci la un set de module obiect. Prima metodă este denumită legare statică (static linking). Când se folosește legarea statică, codul obiect al funcțiilor folosite este ''cuplat'' în fișierul executabil al aplicației. Acest lucru generează programe executabile de dimensiune mare și irosește memoria dacă mai multe instanțe ale aceluiași program sunt rulate în același timp (fiecare are o copie proprie a funcțiilor utilizate). | + | Pentru a putea lega un program cu o bibliotecă, aceasta trebuie să fie prezentă în sistem. Pe sistemele Linux (și nu numai) sunt două modalități de a realizarea legarea unei biblioteci la un set de module obiect. |
- | | + | * Prima metodă este denumită legare statică (static linking). Când se folosește legarea statică, codul obiect al funcțiilor folosite este ''cuplat'' în fișierul executabil al aplicației. Acest lucru generează programe executabile de dimensiune mare și irosește memoria dacă mai multe instanțe ale aceluiași program sunt rulate în același timp (fiecare are o copie proprie a funcțiilor utilizate). |
- | Cealaltă metodă este legarea dinamică (dynamic linking). Legarea dinamică utilizează biblioteci care permit programatorului să refere funcții din cadrul aplicației, fără însă a lega codul funcțiilor în fișierul executabil. Bibliotecile dinamice sunt apelate de sistemul de operare și pot fi partajate de mai multe programe. În sistemele Linux acestea sunt biblioteci shared-object (cu extensia .so). | + | * Cealaltă metodă este legarea dinamică (dynamic linking). Legarea dinamică utilizează biblioteci care permit programatorului să refere funcții din cadrul aplicației, fără însă a lega codul funcțiilor în fișierul executabil. Bibliotecile dinamice sunt apelate de sistemul de operare și pot fi partajate de mai multe programe. În sistemele Linux acestea sunt biblioteci shared-object (cu extensia .so). |
Legarea se face folosind opțiunea ''-l'' transmisă comenzii ''gcc''. Astfel, dacă se dorește folosirea unor funcții din ''math.h'', trebuie legată biblioteca matematică. | Legarea se face folosind opțiunea ''-l'' transmisă comenzii ''gcc''. Astfel, dacă se dorește folosirea unor funcții din ''math.h'', trebuie legată biblioteca matematică. | ||