Differences

This shows you the differences between two versions of the page.

Link to this comparison view

so:laboratoare:laborator-05 [2018/05/04 11:13]
sandu.dorogan [Alocarea memoriei în Linux]
so:laboratoare:laborator-05 [2020/03/24 00:28] (current)
andrei.baronescu [Exercițiul 6 - Stack overflow]
Line 9: Line 9:
  
   * TLPI - Chapter 7, ''​Memory Allocation''​   * TLPI - Chapter 7, ''​Memory Allocation''​
 +
 +===== Link-uri către secțiuni utile =====
 +
 +  * [[#​Gestiunea memoriei]]
 +  * [[#Spațiul de adresă al unui proces]]
 +  * [[#​Alocarea/​Dealocarea memoriei]]
 +  * [[#Lucru cu memoria - Probleme]]
 +    * [[#GDB - Detectarea zonei de acces nevalid de tip page fault]]
 +    * [[#mcheck - verificarea consistenței heap-ului]]
 +  * [[#Leak-uri de memorie]]
 +    * [[#​Valgrind]]
 +    * [[#mtrace]]
 +    * [[#Dublă dealocare]]
 +  ​
  ===== Gestiunea memoriei =====  ===== Gestiunea memoriei =====
  
Line 23: Line 37:
  
 Este, în consecință,​ fundamentală cunoașterea contextului în care acționează subsistemul de gestiune a memoriei și înțelegerea interfeței puse la dispoziție programatorului de către sistemul de operare. Este, în consecință,​ fundamentală cunoașterea contextului în care acționează subsistemul de gestiune a memoriei și înțelegerea interfeței puse la dispoziție programatorului de către sistemul de operare.
 +
 ===== Spațiul de adresă al unui proces ===== ===== Spațiul de adresă al unui proces =====
  
Line 842: Line 857:
 ====== Exerciții ====== ====== Exerciții ======
  
-===== Exercițiul 0 - Joc interactiv (2p) ===== 
  
-  * Detalii desfășurare [[http://​ocw.cs.pub.ro/​courses/​so/​meta/​notare#​joc_interactiv|joc]]. +===== Linux =====
- +
- +
- +
- +
-===== Linux (9p) =====+
  
 <note important>​În rezolvarea laboratorului folosiți arhiva de sarcini [[http://​elf.cs.pub.ro/​so/​res/​laboratoare/​lab05-tasks.zip | lab05-tasks.zip]]</​note>​ <note important>​În rezolvarea laboratorului folosiți arhiva de sarcini [[http://​elf.cs.pub.ro/​so/​res/​laboratoare/​lab05-tasks.zip | lab05-tasks.zip]]</​note>​
Line 855: Line 864:
 <note tip>​Pentru a vă ajuta la implementarea exercițiilor din laborator, în directorul ''​utils''​ din arhivă există un fișier ''​utils.h''​ cu funcții utile. <note tip>​Pentru a vă ajuta la implementarea exercițiilor din laborator, în directorul ''​utils''​ din arhivă există un fișier ''​utils.h''​ cu funcții utile.
 </​note>​ </​note>​
-==== Exercițiul 1 - Zone de stocare a variabilelor ​(0.5p) ​====+==== Exercițiul 1 - Zone de stocare a variabilelor ====
  
 Intrați în directorul ''​1-counter''​ și implementați funcția ''​inc()''​ care întoarce de fiecare dată un întreg reprezentând numărul de apeluri până în momentul respectiv al funcției ''​inc''​ (**nu** aveți voie să folosiți variabile globale). Intrați în directorul ''​1-counter''​ și implementați funcția ''​inc()''​ care întoarce de fiecare dată un întreg reprezentând numărul de apeluri până în momentul respectiv al funcției ''​inc''​ (**nu** aveți voie să folosiți variabile globale).
  
  
-==== Exercițiul 2 - Spațiul de adresă al unui proces ​(1p) ====+==== Exercițiul 2 - Spațiul de adresă al unui proces ====
   ​   ​
 Intrați în directorul ''​2-adr_space''​ și deschideți sursa ''​adr_space.c''​. În alt terminal compilați și rulați programul. Observați zonele de memorie din executabil în care sunt salvate variabilele,​ folosind comanda:<​code bash> Intrați în directorul ''​2-adr_space''​ și deschideți sursa ''​adr_space.c''​. În alt terminal compilați și rulați programul. Observați zonele de memorie din executabil în care sunt salvate variabilele,​ folosind comanda:<​code bash>
Line 878: Line 887:
 </​note>​ </​note>​
  
-==== Exercițiul 3 - Alocarea, realocarea și dezalocarea memoriei ​(1p) ====+==== Exercițiul 3 - Alocarea, realocarea și dezalocarea memoriei ====
  
 Intrați în directorul ''​3-alloc'',​ compilați și rulați programul ''​alloc''​. Intrați în directorul ''​3-alloc'',​ compilați și rulați programul ''​alloc''​.
Line 890: Line 899:
 Revedeți secțiunile [[#​valgrind|Valgrind]] și [[#alocarea memoriei in linux|Alocarea memoriei în Linux]] din laborator.</​note>​ Revedeți secțiunile [[#​valgrind|Valgrind]] și [[#alocarea memoriei in linux|Alocarea memoriei în Linux]] din laborator.</​note>​
  
-==== Exercițiul 4 - Rezolvarea unei probleme de tip Segmentation Fault (1p) ====+==== Exercițiul 4 - Rezolvarea unei probleme de tip Segmentation Fault ====
  
-Intrați în directorul ''​4-gdb''​ și inspectați sursa. Programul ar trebui să citescă un mesaj de la ''​stdin''​ și să-l afișeze. Compilați și rulați sursa. Rulați încă o dată programul din ''​gdb''​ (revedeți [[so:​laboratoare-2013:​resurse:​gdb#​rulare gdb|rularea unui program din gdb]]).+Intrați în directorul ''​4-gdb''​ și inspectați sursa. Programul ar trebui să citescă un mesaj de la ''​stdin''​, să îi transforme fiecare literă în majusculă ​și apoi să-l afișeze. Compilați și rulați sursa.
  
-Pentru a identifica exact unde crapă programul ​folosiți comanda ​[[http://​inside.mines.edu/​fs_home/​lwiencke/​elab/​gdb/​gdb_42.html ​backtrace]]. Pentru detalii despre comenzile ​din gdb folosițcomanda ''​help''​:<code bash> +Rulați încă o dată programul ​din ''​gdb''​ (revedeți [[so:​laboratoare-2013:​resurse:gdb#rulare gdb|rularea unui program ​din gdb]] ș ​[[#​acces nevalid | detectarea unui acces nevalid de tip page fault]]): 
-(gdb) help +<code bash> 
-</code>+(gdb) run 
 +Starting program: ​/home/​student/​lab05/​skel/​lin/​4-gdb/​fault  
 +Give input string:text
  
-Schimbațframe-ul curent cu frame-ul funcției ''​main''​ (revedeți [[#acces nevalid | detectarea unui acces nevalid de tip page fault]]):<code bash> +Program received signal SIGSEGV, Segmentation fault. 
-(gdb) frame main+0x0000555555554809 in upper_string (msg=0x0) at fault.c:​27 
 +27              while (msg[i] != '\0') { 
 +(gdb) bt 
 +#0  0x0000555555554809 in upper_string (msg=0x0) at fault.c:27 
 +#1  0x0000555555554835 in main (at fault.c:40 
 +(gdb) 
 </​code>​ </​code>​
  
-Inspectați valoarea variabilei ''​buf'':<​code bash> 
-(gdb) print buf 
-</​code>​ 
  
-Acum dorim să vedem de ce este ''​buf = NULL'',​ urmărind pașii:+Acum dorim să vedem de ce este ''​msg = NULL'',​ urmărind pașii:
    * Omorâți actualul proces:<​code bash>    * Omorâți actualul proces:<​code bash>
 (gdb) kill (gdb) kill
 </​code>​ </​code>​
-   * Puneți un breakpoint la începutul funcției ''​main'':<​code bash> +   * Puneți un breakpoint la începutul funcției ''​read_message'':<​code bash> 
-(gdb) break main+(gdb) break read_message
 </​code>​ </​code>​
-   ​* ​Rulați programul și inspectați valoarea lui ''​buf'' ​înainte și după apelul funcției ​''​malloc'' ​(folosiți ''​next''​ pentru a trece la instrucțiunea următoare, fără a urmări apelul ​de funcție).+   ​* ​Finalizați funcția:<​code bash> 
 +(gdb) finish 
 +Run till exit from #0  read_message () at fault.c:​14 
 +Give input string:​text 
 +0x0000555555554825 in main () at fault.c:​38 
 +38              message = read_message();​ 
 +Value returned is $1 = 0x0 
 +</​code>​ 
 + 
 +   * După cum puteți vedea, ​''​read_message'' ​returneză ''​0x0'' ​în loc de adresa mesajului citit.
    * Explicați sursa erorii, apoi rezolvați-o.    * Explicați sursa erorii, apoi rezolvați-o.
-==== Exercițiul 5 - Lucru cu memoria - Valgrind ​(1p) ====+ 
 +<note tip> 
 +  * https://​stackoverflow.com/​questions/​40290049/​why-does-gcc-return-0-instead-of-the-address-of-a-stack-allocated-variable 
 +  * https://​github.com/​gcc-mirror/​gcc/​commit/​f22a2cb7500755d69ee5965985d8621c735579c0 
 +</​note>​ 
 +==== Exercițiul 5 - Lucru cu memoria - Valgrind ====
  
 Intrați în directorul ''​5-struct''​ și completați fișierul ''​struct.c''​ conform comentariilor marcate cu ''​TODO''​. Intrați în directorul ''​5-struct''​ și completați fișierul ''​struct.c''​ conform comentariilor marcate cu ''​TODO''​.
Line 925: Line 952:
    * Revedeți secțiunea [[#​valgrind|Valgrind]] din laborator. ​    * Revedeți secțiunea [[#​valgrind|Valgrind]] din laborator. ​
  
-==== Exercițiul 6 - Stack overflow ​(2p) ====+==== Exercițiul 6 - Stack overflow ====
  
 Intrați în directorul 6-stack și inspectați sursa și completați problemele marcate cu //TODO1// astfel: Intrați în directorul 6-stack și inspectați sursa și completați problemele marcate cu //TODO1// astfel:
Line 931: Line 958:
       * în funcția ''​take_snapshot''​ salvați în structura de date ce reține imaginea stivei câmpurile adresă și valoare.       * în funcția ''​take_snapshot''​ salvați în structura de date ce reține imaginea stivei câmpurile adresă și valoare.
  
-Ce reține structura ''​stack_elements''?​+Ce reține structura ''​stack_element''?​
  
 Funcția ''​f2''​ pune pe stivă un vector de 3 întregi. În ce ordine sunt puse elementele vectorului pe stivă? Funcția ''​f2''​ pune pe stivă un vector de 3 întregi. În ce ordine sunt puse elementele vectorului pe stivă?
Line 938: Line 965:
  
 <note tip> <note tip>
-Dezasamblați executabilul. Observați că înainte de call ''​f2''​ se pune pe stivă ''​instruction pointer-ul(eip)''​ care este adresa primului byte de după call. La intrarea în funcție controlul s-a transmis de la caller la callee. Acesta din urmă salvează vechiul ''​base pointer(ebp)''​ iar ebp va conține adresa vârfului stivei.+Dezasamblați executabilul. Observați că înainte de call ''​f2''​ se pune pe stivă ''​instruction pointer-ul(eip) / rip (x86-64)''​ care este adresa primului byte de după call. La intrarea în funcție controlul s-a transmis de la caller la callee. Acesta din urmă salvează vechiul ''​base pointer(ebp) / rbp (x86-64)''​ iar ebp va conține adresa vârfului stivei.
 </​note>​ </​note>​
  
-Folosiți gdb pentru a afla informații despre cum este pus array-ul pe stivă ​și ce index trebuie suprascris: <code bash>+Folosiți gdb pentru a afla informații despre cum este pus array-ul pe stivă: <code bash>
 (gdb) break f2 (gdb) break f2
 (gdb) run (gdb) run
Line 947: Line 974:
 </​code>​ </​code>​
  
-Aveți grijă la proctectori ​de stivă [[https://​mudongliang.github.io/​2016/​05/​24/​stack-protector.html|Stack protectors]].+Aveți grijă la protectori ​de stivă [[https://​mudongliang.github.io/​2016/​05/​24/​stack-protector.html|Stack protectors]].
  
-In funcția ''​f2''​ bufferul ''​v''​ se află pe stivă sub adresa de return a funcției (IP-ul la care se întoarce programul dupa ce execută ''​f2''​). Scriind în bufferul ''​v''​ mai multe elemente decat are acesta alocate pe stivă, vom putea suprascrie adresa de return a lui ''​f2''​ cu o alta adresă (aici, adresa funcției ''​show_message''​). Atenție, după adresa de return este salvat pe stivă base pointerul și abia apoi găsim și bufferul ''​v''​.+In funcția ''​f2''​ bufferul ''​v''​ se află pe stivă sub adresa de return a funcției (IP-ul la care se întoarce programul dupa ce execută ''​f2''​). Scriind în bufferul ''​v''​ mai multe elemente decat are acesta alocate pe stivă, vom putea suprascrie adresa de return a lui ''​f2''​ cu o altă adresă (aici, adresa funcției ''​show_message''​). Atenție, după adresa de return este salvat pe stivă base pointerul și abia apoi găsim și bufferul ''​v''​.
  
 Folosindu-vă de vectorul ''​v''​ **fortați execuția** funcției ''​show_message''​ **fără** a o apela explicit. Astfel, după apelul funcției ''​f2'',​ fluxul programului nu se va mai întoarce în funcția ''​f1'',​ ci va executa ''​show_message''​. Urmăriți comentariile marcate cu //TODO2// (revedeți partea din laborator referitoare la [[#stiva | stivă ]]) Folosindu-vă de vectorul ''​v''​ **fortați execuția** funcției ''​show_message''​ **fără** a o apela explicit. Astfel, după apelul funcției ''​f2'',​ fluxul programului nu se va mai întoarce în funcția ''​f1'',​ ci va executa ''​show_message''​. Urmăriți comentariile marcate cu //TODO2// (revedeți partea din laborator referitoare la [[#stiva | stivă ]])
 +Folosiți-vă de cum arată stiva pentru a afla indexul în cadrul vectorului ''​vv''​ la care se află IP-ul.
 +
  
 <note tip> <note tip>
Line 957: Line 986:
 </​note>​ </​note>​
  
-==== Exercițiul 7 - Detectare probleme de lucru cu memoria ​(1p) ====+==== Exercițiul 7 - Detectare probleme de lucru cu memoria ====
  
 În directorul ''​7-trim''​ analizați programul ''​trim.c'',​ compilați și rulați executabilul ''​trim''​. În directorul ''​7-trim''​ analizați programul ''​trim.c'',​ compilați și rulați executabilul ''​trim''​.
Line 963: Line 992:
 Încercați să detectați problema folosind gdb (revedeți tehnicile folosite la exercițiul 3). Încercați să detectați problema folosind gdb (revedeți tehnicile folosite la exercițiul 3).
 Care este problema? Cum o rezolvați? Care este problema? Cum o rezolvați?
-==== Exercițiul 8 - Endianess ​(1p) ====+ 
 +==== Exercițiul 8 - Endianess ====
  
 Intrați în directorul ''​8-endian''​ și inspectați sursa ''​endian.c''​. Folosindu-vă de variabila ''​w''​ afișați ​ numărul ''​n=0xDEADBEEF''​. Intrați în directorul ''​8-endian''​ și inspectați sursa ''​endian.c''​. Folosindu-vă de variabila ''​w''​ afișați ​ numărul ''​n=0xDEADBEEF''​.
Line 970: Line 1000:
  
  
-==== Exercițiul 9 - Lucrul cu stiva (0.5p) ​====+<​hidden>​==== Exercițiul 9 - Lucrul cu stiva ====
  
 Intrați în directorul ''​9-bad_stack''​ și analizați fișierul ''​bad_stack.c''​. Compilați și rulați programul. Intrați în directorul ''​9-bad_stack''​ și analizați fișierul ''​bad_stack.c''​. Compilați și rulați programul.
Line 981: Line 1011:
  
 <note tip>​Indicație:​ Mutați variabila ''​lab_so''​ din funcția ''​my_fun()''​ într-o altă zonă de memorie.</​note>​ <note tip>​Indicație:​ Mutați variabila ''​lab_so''​ din funcția ''​my_fun()''​ într-o altă zonă de memorie.</​note>​
-===== Exerciții BONUS (3 SO Karma) ​===== +</​hidden>​ 
 +===== Exerciții BONUS ===== 
  
 ==== BONUS Windows ==== ==== BONUS Windows ====
  
-=== 1 so karma - Realizarea unui wrapper pentru funcțiile malloc și free ===+=== Realizarea unui wrapper pentru funcțiile malloc și free ===
  
 Deschideți proiectul Visual Studio din directorul ''​malloc-wrapper''​ și inspectați cele două fișiere existente: ''​xmalloc.c''​ și ''​xmalloc.h''​. Deschideți proiectul Visual Studio din directorul ''​malloc-wrapper''​ și inspectați cele două fișiere existente: ''​xmalloc.c''​ și ''​xmalloc.h''​.
Line 995: Line 1026:
 De ce este mai dificil să se realizeze o funcție ''​xfree''​ care să realizeze aceleași operații? De ce este mai dificil să se realizeze o funcție ''​xfree''​ care să realizeze aceleași operații?
  
-=== 1 so karma - Program de test pentru wrapperul xmalloc ===+=== Program de test pentru wrapperul xmalloc ===
  
 Analizați fișierul ''​test.c''​ și implementați funcțiile ''​tensor_alloc'',​ respectiv ''​tensor_free''​ care alocă/​dealocă un vector tridimensional (tensor). Folosiți funcțiile ''​xmalloc''​ și ''​xfree''​ implementate în cadrul exercițiului anterior (urmăriți comentariile marcate cu ''​TODO''​). Analizați fișierul ''​test.c''​ și implementați funcțiile ''​tensor_alloc'',​ respectiv ''​tensor_free''​ care alocă/​dealocă un vector tridimensional (tensor). Folosiți funcțiile ''​xmalloc''​ și ''​xfree''​ implementate în cadrul exercițiului anterior (urmăriți comentariile marcate cu ''​TODO''​).
Line 1001: Line 1032:
 ==== BONUS Linux ==== ==== BONUS Linux ====
  
-=== 1 so karma - Realizarea unei implementări sumare a funcției malloc ===+=== Realizarea unei implementări sumare a funcției malloc ===
  
 Urmăriți în ''​man''​ specificarea apelurilor [[http://​linux.die.net/​man/​2/​brk | brk]] și [[http://​linux.die.net/​man/​2/​sbrk | sbrk]]. Folosind acest apel de sistem, completați implementarea funcției [[http://​linux.die.net/​man/​3/​malloc | malloc ]] din sursa ''​my_malloc.c''​. Va trebui întâi să extindeți limita curentă a heap-ului (program break) cu valoarea cerută pentru alocare. Urmăriți în ''​man''​ specificarea apelurilor [[http://​linux.die.net/​man/​2/​brk | brk]] și [[http://​linux.die.net/​man/​2/​sbrk | sbrk]]. Folosind acest apel de sistem, completați implementarea funcției [[http://​linux.die.net/​man/​3/​malloc | malloc ]] din sursa ''​my_malloc.c''​. Va trebui întâi să extindeți limita curentă a heap-ului (program break) cu valoarea cerută pentru alocare.
so/laboratoare/laborator-05.1525421632.txt.gz · Last modified: 2018/05/04 11:13 by sandu.dorogan
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0