C++ POO Lab Lucrarea 1: Diferență între versiuni

De la WikiLabs
Jump to navigationJump to search
Fără descriere a modificării
Fără descriere a modificării
 
(Nu s-au afișat 6 versiuni intermediare efectuate de alți 2 utilizatori)
Linia 1: Linia 1:
În acest laborator ne vom reaminti sintaxa limbajului C, vom exersa utilizarea mediului de dezvoltare Netbeans și a ''debugger''-ului.
În acest laborator ne vom reaminti sintaxa limbajului C, vom exersa utilizarea mediului de dezvoltare CLion și a ''debugger''-ului.


== Tool-ul de depanare GDB ==
== Tool-ul de depanare GDB ==
Depanatorul GNU, cunoscut drept GDB (GNU debugger), este depanatorul standard pentru sistemul de software GNU.<br>
Depanatorul GNU, cunoscut drept GDB (GNU debugger), este depanatorul standard pentru sistemul de software GNU.<br>
Scopul unui depanator precum GDB este de a permite utilizatorului să vadă ce se întâmplă în interiorul unui alt program în timp ce acesta se execută sau ce s-a întâmplat cu programul în momentul în care acesta a dat crash.<br>
Scopul unui depanator precum GDB este de a permite utilizatorului să vadă ce se întâmplă în interiorul unui alt program în timp ce acesta se execută (pentru a determina motivul rezultatelor necorespunzătoare) sau ce s-a întâmplat cu programul în momentul în care a fost întreruptă execuţia în mod neaşteptat.<br><br>
GDB este capabil de a face 4 mari categorii de operații (și alte tipuri de operații ce duc la îndeplinirea celor 4):
 
GDB este capabil de a îndeplini 4 categorii de operații (și alte operaţii intermediare lor):
* să pornească programul, specificând orice ar putea interveni în buna funcționare a acestuia;
* să pornească programul, specificând orice ar putea interveni în buna funcționare a acestuia;
* să facă programul să se oprească din execuție în anumite condiții specificate de utilizator;
* să determine o pauză in execuţia programului în anumite condiții specificate de utilizator;
* să examineze ce s-a întâmplat în momentul opririi programului;
* să examineze ce s-a întâmplat în momentul opririi programului;
* să schimbe anumite lucruri în program pentru a putea corecta efectele unui bug și a investiga urmările altuia.<br>
* să modifice anumite valori în program pentru a putea corecta efectele unui bug și a investiga urmările altuia.<br>
Odată pornit, GDB citește comenzi din terminal până la întâlnirea comenzii de ieșire "quit".<br>
Odată pornit, GDB citește comenzi din terminal până la întâlnirea comenzii de ieșire "quit".<br>
<div class="regula">'''<font color="red"> Atenție:</font>''' Pentru a putea folosi debugger-ul, la generarea fișierului executabil trebuie folosită opțiunea '''-g''', care adaugă simboluri de debug în executabil, fără de care depanarea nu este posibilă. (vezi [http://wiki.dcae.pub.ro/index.php/PC_Laborator_1 Laboratorul 1])</div>
<div class="regula">'''<font color="red"> Atenție:</font>''' Pentru a putea folosi debugger-ul, la generarea fișierului executabil trebuie folosită opțiunea '''-g''', care adaugă simboluri de debug în executabil, fără de care depanarea nu este posibilă. (vezi [http://wiki.dcae.pub.ro/index.php/PC_Laborator_1 Laboratorul 1])</div>
Linia 103: Linia 104:
   ''' '''
   ''' '''
   '''Breakpoint 1, main () at suma_fact.c:20'''
   '''Breakpoint 1, main () at suma_fact.c:20'''
   '''20         scanf("%d", &n);'''
   '''20         scanf("%d", &n);'''
   '''(gdb) '''
   '''(gdb) '''
Trecem mai departe și introducem o valoare pentru n:
Trecem mai departe și introducem o valoare pentru n:
   '''(gdb) next'''
   '''(gdb) next'''
   '''Introduceti un numar natural mai mic sau egal cu 8: 6 '''
   '''Introduceti un numar natural mai mic sau egal cu 8: 6 '''
   '''21     }while(n<0 || n>8);'''
   '''21     }while(n<0 || n>8);'''
   '''(gdb) '''
   '''(gdb) '''
Vom parcurge programul pas cu pas până la apelarea funcției ''factorial'':
Vom parcurge programul pas cu pas până la apelarea funcției ''factorial'':
   '''(gdb) n'''
   '''(gdb) n'''
   '''22     unsigned int suma = 0;'''
   '''22     unsigned int suma = 0;'''
   '''(gdb) n'''
   '''(gdb) n'''
   '''23     for(i=0; i<=n; i++){'''
   '''23     for(i=0; i<=n; i++){'''
   '''(gdb) n'''
   '''(gdb) n'''
   '''24         suma += factorial(i);'''
   '''24         suma += factorial(i);'''
   '''(gdb) s'''
   '''(gdb) s'''
   '''factorial (n=0) at suma_fact.c:4'''
   '''factorial (n=0) at suma_fact.c:4'''
   '''4     if(n==0){'''
   '''4    if(n==0){'''
   '''(gdb) s'''
   '''(gdb) s'''
   '''5         return 1;'''
   '''5        return 1;'''
   '''(gdb) s'''
   '''(gdb) s'''
   '''13 }'''
   '''13 }'''
   '''(gdb) s'''
   '''(gdb) s'''
   '''main () at suma_fact.c:23'''
   '''main () at suma_fact.c:23'''
   '''23     for(i=0; i<=n; i++){'''
   '''23     for(i=0; i<=n; i++){'''
   '''(gdb) s'''
   '''(gdb) s'''
   '''24         suma += factorial(i);'''
   '''24         suma += factorial(i);'''
   '''(gdb) s'''
   '''(gdb) s'''
   '''factorial (n=1) at suma_fact.c:4'''
   '''factorial (n=1) at suma_fact.c:4'''
   '''4     if(n==0){'''
   '''4    if(n==0){'''
   '''(gdb) s'''
   '''(gdb) s'''
   '''8     unsigned int fact=0;'''
   '''8    unsigned int fact=0;'''
   '''(gdb) s'''
   '''(gdb) s'''
   '''9     for(i=1; i<=n; i++){'''
   '''9    for(i=1; i<=n; i++){'''
   '''(gdb) s'''
   '''(gdb) s'''
   '''10         fact *= i;'''
   '''10         fact *= i;'''
   '''(gdb) s'''
   '''(gdb) s'''
   '''9     for(i=1; i<=n; i++){'''
   '''9    for(i=1; i<=n; i++){'''
   '''(gdb) s'''
   '''(gdb) s'''
   '''12     return fact;'''
   '''12     return fact;'''
   '''(gdb) print fact'''
   '''(gdb) print fact'''
   '''$1 = 0'''
   '''$1 = 0'''
Linia 149: Linia 150:
   '''A debugging session is active.'''
   '''A debugging session is active.'''
   ''' '''
   ''' '''
   ''' Inferior 1 [process 4279] will be killed.'''
   '''   Inferior 1 [process 4279] will be killed.'''
   ''' '''
   ''' '''
   '''Quit anyway? (y or n) y '''
   '''Quit anyway? (y or n) y '''
Linia 155: Linia 156:
<div class="regula"> ''' Observație: ''' Pentru a putea intra în interiorul funcției ''factorial'' este absolut necesar să se folosească comanda '''step''' și nu comanda '''next''' care ar trece peste acea linie 24 fără a intra în corpul funcției ''factorial''.</div>
<div class="regula"> ''' Observație: ''' Pentru a putea intra în interiorul funcției ''factorial'' este absolut necesar să se folosească comanda '''step''' și nu comanda '''next''' care ar trece peste acea linie 24 fără a intra în corpul funcției ''factorial''.</div>


După acest laborator veți putea folosi IDE-ul Netbeans pentru a scrie și depana programe în C. Totodată veți relua și recapitula noțiunile legate de pointeri în C.
După acest laborator veți putea folosi IDE-ul CLion pentru a scrie și depana programe în C. Totodată veți relua și recapitula noțiunile legate de pointeri în C.


= Utilizarea IDE-ului Netbeans =
= Utilizarea IDE-ului CLion =


[https://netbeans.org/ Netbeans] este un mediu integrat de dezvoltare (IDE) open-source și gratuit care permite dezvoltarea de programe în limbajele Java, C, C++, Javascript, HTML, PHP și Groovy. Netbeans nu instalează și compilatoare pentru Java și C/C++, acestea trebuie instalate manual, în prealabil.  
[https://www.jetbrains.com/clion CLion] este un mediu integrat de dezvoltare (IDE) care permite dezvoltarea de programe în limbajele C și C++. CLion nu instalează și compilator pentru C/C++, acesta trebuie instalat manual, în prealabil.  


<div class="regula"><span style="color: red; font-weight: bold">Atenție:</span> Imaginea de Linux folosită la Programarea Calculatoarelor are deja instalat compilatorul de C.</div>
<div class="regula"><span style="color: red; font-weight: bold">Atenție:</span> Imaginea de Linux folosită la Programarea Calculatoarelor are deja instalat compilatorul de C.</div>
Linia 179: Linia 180:
<div class="regula"><span style="color: red; font-weight: bold">Atenție:</span> Nu uitați ca la instalare să bifați în lista de pachete și compilatorul de C (<code>gcc</code>), <code>make</code> și <code>git</code>.</div>
<div class="regula"><span style="color: red; font-weight: bold">Atenție:</span> Nu uitați ca la instalare să bifați în lista de pachete și compilatorul de C (<code>gcc</code>), <code>make</code> și <code>git</code>.</div>


== Instalarea Netbeans ==
== Instalarea CLion ==
 
De la adresa https://netbeans.org/downloads/ puteți descărca kitul de instalare pentru sistemul vostru de operare (imaginea de Virtualbox cu Linux folosită la Programarea Calculatoarelor ruelază un Linux pe 32 de biți). Descărcați una din variantele care suporta C/C++ ('''C/C++''' sau '''All''').
 
=== Instalare Netbeans în Linux ===
 
Fișierul descărcat pentru Linux va avea extensia '''.sh'''. Pentru a instala programul, deschideți un terminal și rulați următoarele comenzi:
 
<syntaxhighlight lang="bash">
cd ~/Downloads # navigare catre directorul unde a fost salvat fisierul descarcat
chmod +x *.sh # activarea fanionului 'executabil' pentru toate fisierele cu extensia .sh
sudo ./netbeans-8.1-cpp-linux-x86.sh # folositi numele corespunzator al fisierului descarcat
</syntaxhighlight>
 
Mai departe urmați pașii din programul de instalare.


=== Instalare Netbeans în Windows ===
De la adresa https://www.jetbrains.com/clion/download/#section=linux puteți descărca kitul de instalare pentru sistemul vostru de operare.
După instalare, urmaţi următorii paşi de configurare, în funcţie de suita de programe aleasă:
* [https://www.jetbrains.com/help/clion/quick-tutorial-on-configuring-clion-on-windows.html#Cygwin Configurare CLion cu Cygwin]
* [https://www.jetbrains.com/help/clion/quick-tutorial-on-configuring-clion-on-windows.html#MinGW  Configurare CLion cu MinGW]


Fișierul descărcat va avea extensia '''.exe'''. Rulați-l și urmăriți instrucțiunile. Veți fi întrebați unde este compilatorul de C/C++. Executabilele pentru acestea sunt în directorul unde ați instalat MinGW sau Cygwin, în subdirectorul <code>/usr/bin</code>.


== Realizarea unui proiect ==
== Realizarea unui proiect ==


Aplicațiile în Netbeans sunt structurate în '''Proiecte'''. O aplicație este un proiect. Nu este suficient să scrieți un fișier sursă C și să-l rulați. Netbeans trebuie să creeze fișiere '''Makefile''' și să pregătească mediul pentru compilare și execuție precum și să fie capabil să vă ofere informații legate de corectitudinea codului și să vă ofere sugestii de îmbunătățire. Pentru a crea un proiect nou, se folosește meniul <code>File - New Project... </code> sau combinația <code>Ctrl-Shift-n</code>:
Odată pornit, CLion oferă posibilitatea de a deschide un proiect existent, sau de a crea unul nou. Vrem să realizăm un proiect nou, aşadar se va alege '''New Project'''.  
 
[[Fișier:netbeans_new_project.png|1000px|Proiect nou]]
 
Mai departe selectați categoria '''C/C++''' și la '''Project''' selectați '''C/C++ Application'''. Va apărea următoarea fereastră:


[[Fișier:netbeans_new_application.png|Aplicație nouă]]
<div class="regula"> ''' Observație: ''' Se poate realiza un nou proiect atunci când altul este deja deschis folosind meniul <code>File - New Project </code> .</div>


Completați următoarele informații:
[[Fișier:Welcome_to_clion.png | 600px | Imaginea 1]]
* '''Project Name''' - numele proiectului/ al aplicației voastre; va fi numele directorului creat de Netbeans pentru proiect;
* '''Project Location''' - directorul unde va fi salvat directorul proiectului de către Netbeans;
* '''Project Folder''' - calea completă până la directorul proiectului; este obținut din concatenarea celor două de mai sus; nu poate fi modificat;
* '''Project Makefile Name''' - numele fișierului Makefile care va fi creat de către Netbeans pentru proiectul vostru;
* '''Create Main File''' - se bifează dacă se dorește crearea unui fișier sursă care să conțină funcția '''main''' și se completează numele acestui fișier (fără extensie); în căsuța de selecție din dreapta se alege limabjul (C sau C++) și standardul folosit pentru compilarea codului și generarea fișierului main;
* '''Build Host''' - numele sau adresa IP a calculatorului unde se realizează compilarea ('''localhost''' este calculatorul pe care lucrați);
* '''Tool Collection''' - dacă există mai multe compilatoare instalate, de aici se alege care compilator este utilizat pentru proiect.


După ce dați click pe '''Finish''', proiectul se va deschide și fereastra se va schimba în modul de editare.
<br> Mai departe se va selecta categoria '''C++ Executable''' şi se va introduce locaţia proiectului.


== Componentele IDE-ului Netbeans ==
<div class="regula"><span style="color: red; font-weight: bold">Atenție:</span> În imagine se observă că locaţia introdusă este '''/home/student/projects/NewProject'''. Se recomandă ca directorul în care se realizează proiectul să aibă numele proiectului, sau un nume sugestiv (în imagine '''NewProject''')</div>


[[Fișier:netbeans_env.png|1000px|Netbeans]]
[[Fișier:New_project_location_clion.png | 600px | Imaginea 2]]


Zonele din imagine sunt:
== Componentele IDE-ului CLion ==


# Zona <span style="color: gold">gabenă</span> - bara de instrumente - conține butoane folosite pentru acces rapid la funcționalitatea cea mai utilizată (compilare, rulare, etc.) și conține:
[[Fișier:CLion_env.png | 1000px | Imaginea 3]]
#* selecția tipului de compilare ('''Debug''' sau '''Release''') are efect asupra nivelului de optimizare comandat compilatorului și selectează sau nu facă simbolurile de debug sunt adăugate executabilului; pe scurt, nu se poate face debug pe executabilul de Release, dar executabilul de Debug este mai lent decât cel de Release;
#* testare în browser, este accesibil doar pentru aplicații web (HTML, PHP, Javascript, etc.), nu și pentru aplicații C/C++;
#* '''Build Project''' - se apelează '''make all''' pentru compilarea programului;
#* '''Clean and Build Project''' - se apelează '''make clean all''' pentru ștergerea binarelor și apoi recompilarea programului;
#* '''Run Project''' - se rulează executabilul generat de build (dacă acesta nu există sau nu este actualizat, se rulează automat '''Build Project''' înainte);
#* '''Debug Project''' - se rulează executabilul generat de build în modul de debug (cu ajutorul GDB, vezi [[PC Laborator 10#Tool-ul de depanare GDB]]), permițând plasarea de breakpoints, execuție pas cu pas, vizualizarea valorilor variabilelor, etc.
#* '''Profile Project''' - indisponibil în C/C++, permite vizualizarea resurselor consumate și ajută la optimizarea programului.
# Zona <span style="color: blue">albastră</span> - conține 4 tab-uri din care importante pentru proiectele în C sunt primele două: '''Projects''' și '''Files'''.
#* '''Projects''' - arată proiectele deschise și tipul lor; în cazul de față este un singur proiect deschis - '''TestProjectHelloWorld'''; sub el se află 5 categorii în care sunt plasate fișierele care fac parte din proiect:
#** ''Header Files'' - fișierele header (cu extensia .h);
#** ''Resource Files'' - diferite fișiere cu resurse folosite de aplicație (fișiere de configurare, xml, imagini, etc.);
#** ''Source Files'' - fișiere sursă C (cu extensia .c);
#** ''Test Files'' - fișiere de test pentru funcțiile din fișierele sursă;
#** ''Important Files'' - fișiere importante pentru proiect (cum ar fi fișierul Makefile).
#* '''Files''' - se poate vedea directorul proiectului cu fișierele și subdirectoarele sale; în directorul proiectului se realizează implicit următoarele subdirectoare:
#** ''build'' - conține fișierele obiect pentru fiecare din surse, pentru fiecare tip de compilare ('''Debug''' sau '''Release''');
#** ''dist'' - conține fișierele executabile pentru fiecare tip de compilare ('''Debug''' sau '''Release''');
#** ''nbproject'' - conține fișiere de configurare pentru proiect.
# Zona <span style="color: green">verde</span> - conține câte un tab pentru fiecare fișier deschis pentru compilare; implicit bara verde se află deasupra ferestrei de editare (portocaliu) dar poate fi mutată.
# Zona <span style="color: orange">portocalie</span> - fereastra de editare a codului ce conține pe bara de sus butoane pentru navigarea rapidă prin fișierele deschise și / sau modificate recent; de remarcat aici este butonul '''History''' care, dacă fișierul este salvat într-un sistem de ''revision control'' (cum ar fi Git), permite vizualizarea istoriei modificărilor fișierului.
# Zona <span style="color: hotpink">roz</span> - listează elementele definite în fișierul deschis în zona portocalie; dacă fișierul este un header sau un fișier sursă C, aici se vor vedea tipurile de date definite, variabilele globale, funcțiile cu argumentele lor, macrourile de preprocesor, etc.; dacă în schimb este deschis un Makefile, se vor vedea toate rețetele definite în Makefile-ul respectiv;
# Zona <span style="color: red">roșie</span> - zona de ''Output'' reprezintă consola unde se afișează rezultatele compilării cât și ieșirea generată de program în timpul execuției, pe ambele stream-uri (stdout și stderr).


== Exemplu de program ==
La crearea unui nou proiect, IDE-ul CLion generează automat fişierul '''main.cpp'''. Acesta conţine un exemplu program ce va fi rescris de către utilizator. <br>


Copiați codul de mai jos înlocuind programul deja existent în fișierul ''main.c'':
Secţiunile marcate în imagine reprezintă:
<syntaxhighlight lang="C">
# Zona <span style="color: green">verde</span> - '''Project view''' indică toate fişierele şi directoarele ce alcătuiesc proiectul.
#include <stdio.h>
# Zona <span style="color: blue">albastră</span> - '''Editor''' este fereastra de vizualizare şi editare a textului
 
# Zona <span style="color: red">roşie</span> - '''Toolbar''' oferă acces rapid pentru operaţiile uzuale. Dintre acestea, cel mai des vom folosi:
int main(){
#*'''Build''' [[Fișier:CLion_build_button.png | 16px]]
    printf("Hello Netbeans!\n");
#*'''Run''' [[Fișier:CLion_run_button.png | 16px]]
    return 0;
#*'''Debug''' [[Fișier:CLion_debug_button.png | 16px]]
}
# Zona <span style="color: gold">galbenă</span> - '''Run''' este zona în care se introduc datele de intrare şi se în care vor fi afişate datele de ieşire.
</syntaxhighlight>
 
Dați apoi click pe '''Run Project''' (simbolul verde ''Play'') sau tastați <code>Ctrl+F11</code>:
 
[[Fișier:netbeans_run.png|1000px|După execuție]]
 
Observați consola din partea de jos a ecranului unde se afișează mesajul "Hello Netbeans" și apoi se semnalează sfârșitul programului raportându-se timpul de execuție.  


== Exemplu de program în modul ''debug'' ==
== Exemplu de program în modul ''debug'' ==
Linia 286: Linia 235:
</syntaxhighlight>
</syntaxhighlight>


Dați click pe numărul liniei 5 (în dreptul definiției variabilei <code>value</code>) și ar trebui ca în loc de numărul liniei să vă apară un pătrat roșu. Acela semnalează un ''breakpoint'' la acea linie. Dați apoi click pe '''Debug Project''' sau tastați <code>F11</code>. Acesta va programul în modul de ''debug'' și astfel se va opri la primul ''breakpoint'':
Pentru a executa programul în modul debug trebuie sa introducem cel puţin un '''breakpoint'''. Astfel indicăm programului unde se va opri pentru a ne acorda control asupra execuţiei, având posibilitatea de a continua execuţia pas cu pas. <br>
 
Introducem un nou breakpoint dând click în dreptul liniei de la care vrem să obţinem controlul. În cazul nostru, vom alege să indroducem un breakpoint chiar la definirea variabilei <code>value</code>.
 
[[Fișier:CLion_breakpoint.png | 1000px | Imaginea 4]]
 
<div class="regula"><span style="color: red; font-weight: bold">Atenție:</span> Când alegem locaţia unui breakpoint trebuie să ţinem cont de următorul aspect: în modul '''debug''' programul se va opri '''înainte''' de a executa linia în dreptul căreia a fost introdus breakpoint-ul!</div>


[[Fișier:netbeans_debug.png|1000px|După execuție]]
În continuare, trebuie se pornim execuţia programului in modul debug [[Fișier:CLion_debug_button.png | 16px]]. Observăm apariţia ferestrei Debug (chenarul albastru, Imaginea 5) ce conţine următoarele:
#Zona <span style="color: gold">galbenă</span> - fereastra cu toate variabilele declarate, împreună cu valorile lor. Momentan nu există nicio variabilă declarată (deoarece linia asupra la care ne-am oprit nu a fost încă executată!)
#Zona <span style="color: red">roşie</span> - Permite trecerea între fereastra pentru procesul de depanare ('''Debugger''') şi fereastra în care se afişează/introduc datele ('''Console''')
#Zona <span style="color: green">verde</span> - Conţine comenzile pentru controlul execuţiei în modul debug (comenzi numite '''stepping actions'''):
#*'''Step over''' [[Fișier:CLion_step_over.png | 16px]] - Execută comenzile de pe linia curentă şi trece la următoarea linie
#*'''Step into''' [[Fișier:CLion_step_into.png | 16px]] - Programul va executa linia curentă iar dacă pe linia curentă există un apel de funcție, se va opri pe prima linie din funcția respectivă. Această comandă este utilă atunci cand pe linia curentă se află un apel de funcţie şi vrem sa studiem comportamentul codului din interiorul funcţiei.
#*'''Step out''' [[Fișier:CLion_step_out.png | 16px]] - Termină de executat funcţia în care se află linia curentă
#*'''Run to cursor''' [[Fișier:CLion_run_to_cursor.png | 16px]] - Execută toate instructiunile până se intâlneste cursorul.


În interfață au apărut două zone noi:
<div class="regula"> ''' Observație: ''' În modul debug, linia curentă este marcată de către mediul de dezvoltare prin colorarea acesteia cu albastru.</div>
# Zona <span style="color: red">roșie</span> - instrumente de control al execuției în modul de debug; în ordine, acestea sunt:
#* '''Finish Debugger Session''' - execuția se încheie și interfața grafică revine la forma anterioară;
#* '''Restart''' - execuția se reia de la începutul programului, oprindu-se la primul ''breakpoint'';
#* '''Pause''' - dacă programul nu este oprit (într-un ''breakpoint''), atunci accesta poate fi întrerupt facând click pe acest buton;
#* '''Continue''' - dacă programul este oprit (într-un ''breakpoint''), atunci el poate fi rulat mai reparte până la următorul ''breakpoint'' cu ajutorul acestui buton;
#* '''Step Over''' - programul va executa linia curentă (inclusiv orice apel de funcție ar fi pe linia curentă) și trece la linia următoare unde se oprește;
#* '''Step Into''' - programul va executa linia curentă iar dacă pe linia curentă există un apel de funcție, se va opri pe prima linie din funcția respectivă;
#* '''Step Out''' - programul va termina de executat funcția curentă și se va opri pe prima linie după linia unde a fost apelată funcția respectivă;
#* '''Run to Cursor''' - programul va executa toate liniile și se va opri pe linia unde este plasat cursorul; dacă acesta nu este plasat în calea execuției programului, acesta se va rula până la final;
#* '''Step Into Last or Selected Function Called From Current Line''' - similar cu '''Step Into''' doar că dacă există mai multe apeluri de funcții pe linia curentă, această opțiune permite selectarea celei în care se va opri programul.


# Zona <span style="color: blue">albastră</span> - vizualizarea stării execuției programului; aveți la dispoziție trei taburi noi:
Alte comenzi utile:
#* '''Variables''' - aici se pot vedea valorile curente ale tuturor variabilelor valide în ''scope''-ul curent al programului; inclusiv aici se pot adăuga ''watches'' care permit vizualizarea valorilor calculate din expresii complexe scrise în limbajul C;
*'''Resume program''' [[Fișier:CLion_resume_project.png | 16px]] - Continuă execuţia pâmă la următorul breakpoint (dacă nu există, se va executa până la final)
#* '''Call Stack''' - aici se poate vedea în orice moment stiva de execuție a programului;
*'''Stop''' [[Fișier:CLion_stop.png | 16px]] - Se opreşte definitv execuţia programului, împreună cu modul debug
#* '''Breakpoints''' - aici se poate vedea lista de ''breakpoints'' din programul curent.
 
[[Fișier:CLion_debug_process.png | 1000px | Imaginea 5]]<br>


Pentru a exersa utilizarea sistemului de debug, realizați următoarele operații:
Pentru a exersa utilizarea sistemului de debug, realizați următoarele operații:
# Parcurgeti tot programul folosind '''Step Over''' și vizualizând valoarea variabilei <code>value</code> la fiecare pas, până la ultima linie din program, unde utilizați '''Continue'''.
# Parcurgeti tot programul folosind '''Step Over''' și vizualizând valoarea variabilei <code>value</code> la fiecare pas, până la ultima linie din program, unde utilizați '''Resume program'''.
# Reporniți aplicația în modul de debug și puneți un al doilea ''breakpoint'' pe linia cu apelul funcției <code>printf</code>.  
# Reporniți aplicația în modul de debug și puneți un al doilea ''breakpoint'' pe linia cu apelul funcției <code>printf</code>.  
# Folosiți '''Continue''' pentru a ajunge la al doilea ''breakpoint''.
# Folosiți '''Resume program''' pentru a ajunge la al doilea ''breakpoint''.
# Odată ajunși acolo, folosiți '''Step In''' pentru a intra în funcția <code>printf</code> (neavând codul sursă, veți vedea codul de asamblare obținut din dezasamblarea fișierului obiect de către GDB).
# Odată ajunși acolo, folosiți '''Step In''' pentru a intra în funcția <code>printf</code> (neavând codul sursă, veți vedea codul de asamblare obținut din dezasamblarea fișierului obiect de către GDB).
# Folosiți '''Step Out''' pentru a reveni în funcția <code>main</code> și apoi '''Continue''' pentru a termina execuția.
# Folosiți '''Step Out''' pentru a reveni în funcția <code>main</code> și apoi '''Resume program''' pentru a termina execuția.
# Reporniți aplicația în modul de debug și realizați un ''watch'' cu valoarea lui <code>value + 1</code>. Vizualizați pas cu pas execuția programului.
 


== Tips & Tricks ==
== Tips & Tricks ==
=== Suport pentru instrumente de ''Revision Control'' ===
Netbeans oferă suport grafic pentru cele mai utilizate intrumente de ''revision control'': SVN, Git, Mercurial, etc. Pentru a crea un repository nou de Git pentru proiectul curent din interfața grafică, puteți da click dreapta pe numele proiectului, apoi '''Versioning -> Initialize Git repository...''':
[[Fișier:netbeans_git_init.png|1000px|Git Init]]
După operațiunea de init, meniul '''Versioning''' se va schimba în '''Git''', de unde se pot realiza toate operațiile cunoscute din Git: add, remove, commit, push, pull, merge, rebase, diff, etc.


=== Formatare automată a codului ===
=== Formatare automată a codului ===


Netbeans oferă opțiunea de a formata automat codul prin selectarea '''Source -> Format'''.  
CLion oferă opțiunea de a formata automat codul prin selectarea '''Code -> Reformat Code'''.  


Ce probleme rezolvă această formatare automată:
Ce probleme rezolvă această formatare automată:
Linia 336: Linia 281:
* numele insuficient de sugestive pentru numele de funcții, structuri sau variabile.
* numele insuficient de sugestive pentru numele de funcții, structuri sau variabile.


Nu uitați de regulile următoare: [[Convenții de cod - C]]
Stilul conform căruia este modificat codul poate fi configurat folosind meniul <code>File|Settings|Editor|CodeStyle</code>
 
=== Generare automată a codului ===
 
CLion oferă posibilitatea de a genera fragmente de cod des înâlnite, precum constructori şi operatori în interiorul claselor. Această acţiune poate fi realizată folosind meniul <code> Code|Generate</code>.


<!--
=== Altele ===
= Exerciții =
* [https://www.jetbrains.com/help/clion/using-todo.html TODO Comments]


*Săptămâna 1
<br> Nu uitați de regulile următoare: [[Convenții de cod - C]]
*# Realizați un proiect nou în Netbeans și scrieți un program care să citească de la tastatură un număr întreg fără semn <code>size</code>. Se va aloca apoi dinamic în HEAP un vector de <code>size</code> valori numerice întregi pe 16 biți. Scrieți o funcție care să citească <code>size</code> valori de la tastatură și să le plaseze în vector. Scrieți apoi o funcție care să găsească valoarea maximă din vector. Apelați în <code>main</code> funcțiile de mai sus și afișați valoarea obținută pe ecran. Nu uitați să dezalocați memoria alocată. Pentru funcțiile de alocare și dezalocare de memorie, puteți recapitula [[PC Laborator 12]].
*# Modificați programul de mai sus astfel încât citirea variabilei <code>size</code> cât și alocarea de memorie să fie făcută într-o funcție separată. Această funcție trebuie să întoarcă un pointer cu adresa de început a vectorului dar și dimensiunea acestuia.
*# Realizați un alt proiect în Netbeans și scrieți un program care să citească de la tastatură un șir de caractere de lungime maximă 255. Folosind aritmetica pointerilor și o singură buclă '''for''', afișați pe ecran doar cifrele din șirul citit.
* Săptămâna 2
*# Realizați un proiect nou în Netbeans și scrieți un program care să citească de la tastatură un număr întreg fără semn <code>size</code>. Scrieți apoi o funcție care să aloce memorie pentru un șir de caractere care să conțină de <code>size</code> ori secvența "ha" (spre exemplu, pentru size == 3, string-ul va trebui să conțină "hahaha"), să umple șirul cu numărul cerut de "ha"-uri și să întoarcă adresa memoriei alocate. În funcția <code>main</code> afișați șirul de caractere (nu uitați la alocare de terminatorul de sfârșit de șir). Nu uitați să dezalocați memoria. Pentru funcțiile de alocare și dezalocare de memorie, puteți recapitula [[PC Laborator 12]].
*# Modificați programul de mai sus astfel încât în loc de secvența "ha", secvența repetată să fie citită de la tastatură cu <code>scanf</code> și trimisă ca argument funcției de alocare.
*# Realizați un alt proiect în Netbeans și scrieți un program care să citească de la tastatură un șir de caractere de lungime maximă 255. Scrieți o singură funcție care să numere și să întoarcă numărul de litere și numărul de cifre din șirul citit. Aceste valori se vor afișa pe ecran în funcția <code>main</code>.
-->

Versiunea curentă din 20 septembrie 2020 09:09

În acest laborator ne vom reaminti sintaxa limbajului C, vom exersa utilizarea mediului de dezvoltare CLion și a debugger-ului.

Tool-ul de depanare GDB

Depanatorul GNU, cunoscut drept GDB (GNU debugger), este depanatorul standard pentru sistemul de software GNU.
Scopul unui depanator precum GDB este de a permite utilizatorului să vadă ce se întâmplă în interiorul unui alt program în timp ce acesta se execută (pentru a determina motivul rezultatelor necorespunzătoare) sau ce s-a întâmplat cu programul în momentul în care a fost întreruptă execuţia în mod neaşteptat.

GDB este capabil de a îndeplini 4 categorii de operații (și alte operaţii intermediare lor):

  • să pornească programul, specificând orice ar putea interveni în buna funcționare a acestuia;
  • să determine o pauză in execuţia programului în anumite condiții specificate de utilizator;
  • să examineze ce s-a întâmplat în momentul opririi programului;
  • să modifice anumite valori în program pentru a putea corecta efectele unui bug și a investiga urmările altuia.

Odată pornit, GDB citește comenzi din terminal până la întâlnirea comenzii de ieșire "quit".

Atenție: Pentru a putea folosi debugger-ul, la generarea fișierului executabil trebuie folosită opțiunea -g, care adaugă simboluri de debug în executabil, fără de care depanarea nu este posibilă. (vezi Laboratorul 1)

Exemplul unei comenzi de compilare în vederea depanării:

  student@pracsis01 ~/Desktop $ gcc -g hello.c -o hello

Comenzi specifice GDB

Cea mai folosită modalitate de a porni tool-ul de depanare este de a scrie gdb în terminal, urmat de numele executabilului ce se dorește a fi depanat.

  student@pracsis01 ~/Desktop $ gdb hello

O parte din comenzile cele mai utilizate ale GDB sunt următoarele (pentru lista completă studiați pagina de manual GDB - man gdb):

Opțiune Efect
break [nume_fișier:] nume_funcție
break [nume_fișier:] număr_linie
Setează un breakpoint (punct de întrerupere) la începutul funcției nume_funcție sau la linia specificată prin număr_linie din fișierul specificat prin nume_fișier.
run [listă_argumente] Pornește programul în execuție (cu lista de argumente, dacă au fost specificate).
bt Backtrace: afișează stiva de program.
print expresie Afișează valoarea unei expresii (valoarea stocată într-o variabilă, valoarea returnată de o funcție etc.).
c Continuă execuția programului (după ce a fost oprit, spre exemplu după un breakpoint).
next Execută următoarea linie de program (după oprire), sărind peste orice apel de funcție care se găsește în această linie.
list [nume_fișier:] nume_funcție Afișează liniile de cod ale programului din vecinătatea locului unde este oprit acum.
step Execută următoarea linie de program (după oprire), intrând în orice funcție apelată de acea linie.
help [nume] Afișează informații despre comanda GDB nume sau informații generale despre utilizarea GDB.
quit Iese din GDB.
Observație: Cele mai multe dintre aceste comenzi pot fi apelate doar prin prima literă a numelui lor.

Spre exemplu, următoarea comandă:

  (gdb) next

este identică cu:

  (gdb) n
Observație: Dacă se apasă pe enter fără a scrie o comandă, se repetă ultima comandă specificată.

Exemplu de depanare

Se dă fișierul sursă suma_fact.c, care conține următoarele instrucțiuni:

#include<stdio.h>

unsigned int factorial(int n) {
    if (n == 0) {
        return 1;
    }
    int i;
    unsigned int fact = 0;
    for (i = 1; i <= n; i++){
        fact *= i;
    }
    return fact;
}


int main() {
    int n, i;
    do {
        printf("Introduceti un numar natural mai mic sau egal cu 8: ");
        scanf("%d", &n);
    } while (n < 0 || n > 8);
    unsigned int suma = 0;
    for (i = 0; i <= n; i++) {
        suma += factorial(i);
    }
    printf("%u\n", suma);
    return 0;
}

Programul își propune să calculeze suma factorialelor de la 0 la n, unde n este introdus de la tastatură. Dacă rulăm programul vom obține ca rezultat numărul 1, indiferent de ce a fost introdus de la tastatură. Ne propunem să descoperim bug-ul folosind GDB.
Compilăm sursa, adăugând simboluri de debug în executabil, după care lansăm în execuție debugger-ul:

  student@pracsis01 ~/Desktop $ gcc -g suma_fact.c -o suma_fact
  student@pracsis01 ~/Desktop $ gdb suma_fact
Atenție: Comanda de mai sus lansează în execuție numai debugger-ul, nu și programul suma_fact.
Observație: Putem observa că am pornit debugger-ul prin faptul că fiecare rând nou din linia de comandă începe acum astfel:
  (gdb)

Punem un breakpoint la linia 20, unde se citește valoarea lui n:

  (gdb) b 20
  Breakpoint 1 at 0x80484c2: file suma_fact.c, line 20.
  (gdb) 

Pornim programul în interiorul debugger-ului:

  (gdb) run
  Starting program: /home/student/Desktop/suma_fact
   
  Breakpoint 1, main () at suma_fact.c:20
  20          scanf("%d", &n);
  (gdb) 

Trecem mai departe și introducem o valoare pentru n:

  (gdb) next
  Introduceti un numar natural mai mic sau egal cu 8: 6 
  21      }while(n<0 || n>8);
  (gdb) 

Vom parcurge programul pas cu pas până la apelarea funcției factorial:

  (gdb) n
  22      unsigned int suma = 0;
  (gdb) n
  23      for(i=0; i<=n; i++){
  (gdb) n
  24          suma += factorial(i);
  (gdb) s
  factorial (n=0) at suma_fact.c:4
  4     if(n==0){
  (gdb) s
  5         return 1;
  (gdb) s
  13  }
  (gdb) s
  main () at suma_fact.c:23
  23      for(i=0; i<=n; i++){
  (gdb) s
  24          suma += factorial(i);
  (gdb) s
  factorial (n=1) at suma_fact.c:4
  4     if(n==0){
  (gdb) s
  8     unsigned int fact=0;
  (gdb) s
  9     for(i=1; i<=n; i++){
  (gdb) s
  10          fact *= i;
  (gdb) s
  9     for(i=1; i<=n; i++){
  (gdb) s
  12      return fact;
  (gdb) print fact
  $1 = 0
  (gdb) 

Observăm că valoarea returnată de funcția factorial pentru orice număr nenul este 0. Acest lucru se datorează inițializării variabilei fact cu valoarea 0 la începutul funcției factorial. Putem ieși din debugger pentru a modifica linia 8 din fișierul sursă suma_fact.c:

  (gdb) q
  A debugging session is active.
   
      Inferior 1 [process 4279] will be killed.
   
  Quit anyway? (y or n) y 
  student@pracsis01 ~/Desktop $
Observație: Pentru a putea intra în interiorul funcției factorial este absolut necesar să se folosească comanda step și nu comanda next care ar trece peste acea linie 24 fără a intra în corpul funcției factorial.

După acest laborator veți putea folosi IDE-ul CLion pentru a scrie și depana programe în C. Totodată veți relua și recapitula noțiunile legate de pointeri în C.

Utilizarea IDE-ului CLion

CLion este un mediu integrat de dezvoltare (IDE) care permite dezvoltarea de programe în limbajele C și C++. CLion nu instalează și compilator pentru C/C++, acesta trebuie instalat manual, în prealabil.

Atenție: Imaginea de Linux folosită la Programarea Calculatoarelor are deja instalat compilatorul de C.

Instalarea GCC

Instalarea GCC în Linux

Pentru instalarea compilatorului de C (GCC) în distribuțiile de Linux provenite din Ubuntu (Ubuntu, Kubuntu, Xubuntu, Mint, LMDE, etc.) se poate folosi comanda:

apt-get install -y build-essential

Instalarea GCC în Windows

Pentru compilarea de programe cu GCC în Windows, aveți nevoie de instalarea acestui compilator care poate fi făcută prin instalarea unuia din următoarele două suite de programe:

Atenție: Nu uitați ca la instalare să bifați în lista de pachete și compilatorul de C (gcc), make și git.

Instalarea CLion

De la adresa https://www.jetbrains.com/clion/download/#section=linux puteți descărca kitul de instalare pentru sistemul vostru de operare. După instalare, urmaţi următorii paşi de configurare, în funcţie de suita de programe aleasă:


Realizarea unui proiect

Odată pornit, CLion oferă posibilitatea de a deschide un proiect existent, sau de a crea unul nou. Vrem să realizăm un proiect nou, aşadar se va alege New Project.

Observație: Se poate realiza un nou proiect atunci când altul este deja deschis folosind meniul File - New Project .

Imaginea 1


Mai departe se va selecta categoria C++ Executable şi se va introduce locaţia proiectului.

Atenție: În imagine se observă că locaţia introdusă este /home/student/projects/NewProject. Se recomandă ca directorul în care se realizează proiectul să aibă numele proiectului, sau un nume sugestiv (în imagine NewProject)

Imaginea 2

Componentele IDE-ului CLion

Imaginea 3

La crearea unui nou proiect, IDE-ul CLion generează automat fişierul main.cpp. Acesta conţine un exemplu program ce va fi rescris de către utilizator.

Secţiunile marcate în imagine reprezintă:

  1. Zona verde - Project view indică toate fişierele şi directoarele ce alcătuiesc proiectul.
  2. Zona albastră - Editor este fereastra de vizualizare şi editare a textului
  3. Zona roşie - Toolbar oferă acces rapid pentru operaţiile uzuale. Dintre acestea, cel mai des vom folosi:
    • Build
    • Run
    • Debug
  4. Zona galbenă - Run este zona în care se introduc datele de intrare şi se în care vor fi afişate datele de ieşire.

Exemplu de program în modul debug

Copiați codul de mai jos înlocuind programul deja existent în fișierul main.c:

#include <stdio.h>

int main(){
    printf("Debugging program...\n");
    int value = 0;
    value = value + 1;
    value++;
    value = value * 2;
    value -= 1;
    printf("Value is now %d!\n", value);
    return 0;
}

Pentru a executa programul în modul debug trebuie sa introducem cel puţin un breakpoint. Astfel indicăm programului unde se va opri pentru a ne acorda control asupra execuţiei, având posibilitatea de a continua execuţia pas cu pas.

Introducem un nou breakpoint dând click în dreptul liniei de la care vrem să obţinem controlul. În cazul nostru, vom alege să indroducem un breakpoint chiar la definirea variabilei value.

Imaginea 4

Atenție: Când alegem locaţia unui breakpoint trebuie să ţinem cont de următorul aspect: în modul debug programul se va opri înainte de a executa linia în dreptul căreia a fost introdus breakpoint-ul!

În continuare, trebuie se pornim execuţia programului in modul debug . Observăm apariţia ferestrei Debug (chenarul albastru, Imaginea 5) ce conţine următoarele:

  1. Zona galbenă - fereastra cu toate variabilele declarate, împreună cu valorile lor. Momentan nu există nicio variabilă declarată (deoarece linia asupra la care ne-am oprit nu a fost încă executată!)
  2. Zona roşie - Permite trecerea între fereastra pentru procesul de depanare (Debugger) şi fereastra în care se afişează/introduc datele (Console)
  3. Zona verde - Conţine comenzile pentru controlul execuţiei în modul debug (comenzi numite stepping actions):
    • Step over - Execută comenzile de pe linia curentă şi trece la următoarea linie
    • Step into - Programul va executa linia curentă iar dacă pe linia curentă există un apel de funcție, se va opri pe prima linie din funcția respectivă. Această comandă este utilă atunci cand pe linia curentă se află un apel de funcţie şi vrem sa studiem comportamentul codului din interiorul funcţiei.
    • Step out - Termină de executat funcţia în care se află linia curentă
    • Run to cursor - Execută toate instructiunile până se intâlneste cursorul.
Observație: În modul debug, linia curentă este marcată de către mediul de dezvoltare prin colorarea acesteia cu albastru.

Alte comenzi utile:

  • Resume program - Continuă execuţia pâmă la următorul breakpoint (dacă nu există, se va executa până la final)
  • Stop - Se opreşte definitv execuţia programului, împreună cu modul debug

Imaginea 5

Pentru a exersa utilizarea sistemului de debug, realizați următoarele operații:

  1. Parcurgeti tot programul folosind Step Over și vizualizând valoarea variabilei value la fiecare pas, până la ultima linie din program, unde utilizați Resume program.
  2. Reporniți aplicația în modul de debug și puneți un al doilea breakpoint pe linia cu apelul funcției printf.
  3. Folosiți Resume program pentru a ajunge la al doilea breakpoint.
  4. Odată ajunși acolo, folosiți Step In pentru a intra în funcția printf (neavând codul sursă, veți vedea codul de asamblare obținut din dezasamblarea fișierului obiect de către GDB).
  5. Folosiți Step Out pentru a reveni în funcția main și apoi Resume program pentru a termina execuția.


Tips & Tricks

Formatare automată a codului

CLion oferă opțiunea de a formata automat codul prin selectarea Code -> Reformat Code.

Ce probleme rezolvă această formatare automată:

  • alinierea liniilor în funcție de blocurile de instrucțiuni și tipurile de statements de pe fiecare linie;
  • plasarea sau eliminarea de spații acolo unde este necasar.

Ce probleme NU rezolvă această formatare automată;

  • lipsa acoladelor de la blocurile if și for;
  • numele insuficient de sugestive pentru numele de funcții, structuri sau variabile.

Stilul conform căruia este modificat codul poate fi configurat folosind meniul File|Settings|Editor|CodeStyle

Generare automată a codului

CLion oferă posibilitatea de a genera fragmente de cod des înâlnite, precum constructori şi operatori în interiorul claselor. Această acţiune poate fi realizată folosind meniul Code|Generate.

Altele


Nu uitați de regulile următoare: Convenții de cod - C