This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision Next revision Both sides next revision | ||
bune-practici [2015/11/30 16:27] catalin.vasile3004 [Segmentation Fault debugging: GDB quicky] |
bune-practici [2015/11/30 16:48] catalin.vasile3004 [Segmentation Fault debugging: GDB quicky] |
||
---|---|---|---|
Line 156: | Line 156: | ||
- Într-o singură etapă se aduc mai multe instrucţiuni din memorie. Accesul la memorie este scump, şi dacă la fiecare instrucţiune de 5-6 bytes ne-am duce în memorie, nu am avea o performanţă foarte bună. Din acest motiv s-a inventat un modul în procesor, numit prefetching, în care se înmagazinează mai multe instrucţiuni de la adresa de la care se aduce cod/instrucţiuni, pentru ca execuţia să fie mai fluidă. | - Într-o singură etapă se aduc mai multe instrucţiuni din memorie. Accesul la memorie este scump, şi dacă la fiecare instrucţiune de 5-6 bytes ne-am duce în memorie, nu am avea o performanţă foarte bună. Din acest motiv s-a inventat un modul în procesor, numit prefetching, în care se înmagazinează mai multe instrucţiuni de la adresa de la care se aduce cod/instrucţiuni, pentru ca execuţia să fie mai fluidă. | ||
- În momentul în care procesorul îşi dă seama că una din instrucţiuni accesează o zonă nevalidă din memorie, trimite un semnal către sistemul de operare. Şi sistemul de operare este tot o bucată de cod care se execută pe procesor. Până când acest semnal trezeşte codul din sistemul de operare, e foarte posibil ca programul să mai fi executat o căruţă de instrucţiuni, din acest motiv, o înşiruire de printf-uri s-ar putea executa şi după instrucţiunea care a produs Segmentation Fault-ul. | - În momentul în care procesorul îşi dă seama că una din instrucţiuni accesează o zonă nevalidă din memorie, trimite un semnal către sistemul de operare. Şi sistemul de operare este tot o bucată de cod care se execută pe procesor. Până când acest semnal trezeşte codul din sistemul de operare, e foarte posibil ca programul să mai fi executat o căruţă de instrucţiuni, din acest motiv, o înşiruire de printf-uri s-ar putea executa şi după instrucţiunea care a produs Segmentation Fault-ul. | ||
- | - Sistemul de operare se trezeşte şi închide forţat programul care a cauzat probleme. Printre datele primite de la semnal se regăseşte şi adresa instrucţiunii care a cauzat Segmentation Fault. Cu un debugger, se pot afla şi din userspace ce instrucţiune a cauzat Segmentation Fault. | + | - Sistemul de operare se trezeşte şi închide forţat programul care a cauzat probleme. Printre datele primite de la semnal se regăseşte şi adresa instrucţiunii care a cauzat Segmentation Fault. Cu un debugger, se poate afla şi din userspace ce instrucţiune a cauzat Segmentation Fault. |
Exemplu de cod cu probleme: | Exemplu de cod cu probleme: | ||
<file asm segfault.asm> | <file asm segfault.asm> | ||
Line 233: | Line 233: | ||
0x08048423 in keep_printing () | 0x08048423 in keep_printing () | ||
</code> | </code> | ||
- | Pentru a vedea ce instrucţiunea a provocat segfault putem da următoarea comandă: | + | Pentru a vedea ce instrucţiunea a provocat segfault, putem da următoarea comandă: |
<code> | <code> | ||
(gdb) display/10i $pc | (gdb) display/10i $pc | ||
Line 252: | Line 252: | ||
* **i**-ul îi spune lui **display** să interpreteze datele de acolo ca şi cum ar fi instrucţiuni | * **i**-ul îi spune lui **display** să interpreteze datele de acolo ca şi cum ar fi instrucţiuni | ||
* **10** îi sune lui **display** câţi operanzi/instrucţiuni de tipul **i** (instrucţiune) să afişeze\\ \\ | * **10** îi sune lui **display** câţi operanzi/instrucţiuni de tipul **i** (instrucţiune) să afişeze\\ \\ | ||
- | Prin ''<keep_printing+some_number>'', **gdb** incearcă să ne arate cam pe unde ar fi această instrucţiune. În cazul nostru instrucţiunea este aproape de label-ul **keep_printing**. | + | Prin ''<keep_printing+some_number>'', **gdb** incearcă să ne arate cam pe unde ar fi această instrucţiune. În cazul nostru instrucţiunea este aproape de label-ul **keep_printing**.\\ |
+ | Pentru a vedea ce valoare a avut un registru la momentul în care s-a declanşat **segfault**-ul, puteţi da: | ||
+ | <code> | ||
+ | (gdb) print $nume_registru | ||
+ | </code> | ||
+ | În cazul nostru s-ar putea să ne intereseze ce valoare are **ecx**. Pentru a afla acest lucru: | ||
+ | <code> | ||
+ | (gdb) print $ecx | ||
+ | </code> | ||
===== Categorie 3 ===== | ===== Categorie 3 ===== | ||
* TODO | * TODO | ||
* TODO | * TODO |