SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our User Agreement and Privacy Policy.
SlideShare uses cookies to improve functionality and performance, and to provide you with relevant advertising. If you continue browsing the site, you agree to the use of cookies on this website. See our Privacy Policy and User Agreement for details.
Successfully reported this slideshow.
Activate your 14 day free trial to unlock unlimited reading.
A static Analyzer for Finding Dynamic Programming Errors
A static Analyzer for Finding Dynamic Programming Errors
1.
A static Analyzer for Finding Dynamic Programming Errors Possamai Lino, 800509 Analisi e Verifica di Programmi 4 Maggio 2006
2.
Introduzione <ul><li>Gli errori dinamici di programmazione appartengono alla classe di errori che sono difficili da rilevare sia manualmente che automaticamente </li></ul><ul><ul><li>Invalid pointer references </li></ul></ul><ul><ul><li>Faulty storage allocation </li></ul></ul><ul><ul><li>Uso di memoria non inizializzata </li></ul></ul><ul><ul><li>Operazioni improprie sulle risorse </li></ul></ul><ul><li>Sono causati nella maggior parte dei casi da interazioni complesse tra componenti del programma. In prodotti commerciali, si stima che sia nell’ordine del 90% degli errori rilevati. </li></ul>
3.
Obiettivi <ul><li>L’obiettivo principale è stato quello di costruire un tool per l’analisi del codice </li></ul><ul><ul><li>che fosse facile da usare come nel caso dei runtime memory debugger, ma che non richieda all’utente di dover eseguire il programma, fornendo quindi i test case, </li></ul></ul><ul><ul><li>che riportasse molti degli errori possibili, </li></ul></ul><ul><ul><li>che l’informazione fosse ricavata esclusivamente dall’analisi del codice sorgente, senza l’uso di annotazioni </li></ul></ul><ul><ul><li>che l’analisi effettuata analizzasse solamente i cammini possibili </li></ul></ul><ul><ul><li>che l’informazione prodotta riguardante gli errori rilevati fosse abbastanza esplicativa in modo tale che l’utente capisca velocemente dove si genera l’errore </li></ul></ul>
4.
Architettura di PRE fix <ul><li>La prima fase consiste nel parsing del codice sorgente in modo tale </li></ul><ul><li>da costruire l’AST, determinando, allo stesso tempo, l’ordine di esecuzione delle funzioni. </li></ul><ul><li>È una fase molto “pesante” in termini di tempo. Può consumare circa il 20-25% del tempo totale di esecuzione </li></ul><ul><li>Bottom up???? </li></ul>
5.
Architettura di PRE fix <ul><li>Per rilevare gli errori inter-procedurali, è necessario simulare l’esecuzione di una funzione su un modello astratto della memoria grazie ad una macchina virtuale. </li></ul><ul><li>Lo stato della memoria viene tracciato durante tutta la simulazione delle funzioni, come anche tra gli archi del grafo delle chiamate. </li></ul><ul><li>Il compito del simulatore è quello di osservare lo stato della memoria nel modello astratto e di costruisce, alla fine, </li></ul><ul><li>un modello di comportamento per la funzione </li></ul><ul><li>simulata. </li></ul>
6.
Architettura di PRE fix 3.x – visione d’insieme
7.
Esempio <ul><li>1 #include <stdlib.h> </li></ul><ul><li>2 #include <stdio.h> </li></ul><ul><li>3 </li></ul><ul><li>4 char *f(int size ) </li></ul><ul><li>5 { </li></ul><ul><li>6 char *result; </li></ul><ul><li>7 </li></ul><ul><li>8 if (size > 0) </li></ul><ul><li>9 result = (char*)malloc(size); </li></ul><ul><li>10 if (size == 1) </li></ul><ul><li>11 return NULL; </li></ul><ul><li>12 result[0] = 0; </li></ul><ul><li>13 return result ; </li></ul><ul><li>14 } </li></ul><ul><li>La funzione f alloca memoria nello heap e la inizializza (se la dimensione richiesta è maggiore di zero). </li></ul><ul><li>Se size=1 , la funzione ritorna NULL. </li></ul><ul><li>Negli altri casi, inizializza a zero la variabile result . </li></ul><ul><li>In questo caso, PRE fix individua tre warning. </li></ul>
8.
Esempio <ul><li>1 #include <stdlib.h> </li></ul><ul><li>2 #include <stdio.h> </li></ul><ul><li>3 </li></ul><ul><li>4 char *f(int size) </li></ul><ul><li>5 { </li></ul><ul><li>6 char *result; </li></ul><ul><li>7 </li></ul><ul><li>8 if (size > 0) </li></ul><ul><li>9 result = (char*)malloc(size); </li></ul><ul><li>10 if (size == 1) </li></ul><ul><li>11 return NULL; </li></ul><ul><li>12 result[0] = 0; </li></ul><ul><li>13 return result; </li></ul><ul><li>14 } </li></ul>example1.c(11) : warning 14: leaking memory problem occurs in function 'f' The call stack when memory is allocated is: example1.c(9) : f Problem occurs when the following conditions are true: example1.c(8) : when 'size > 0' here example1.c(10) : when 'size == 1' here Path includes 4 statements on the following lines: 8 9 10 11 example1.c(9) : used system model 'malloc' for function call: 'malloc(size)' function returns a new memory block memory allocated Sorgente: Output dell’analisi:
11.
Limitazioni <ul><li>Per programmi commerciali, quali per esempio Apache o Mozilla, l’analisi del codice è molto lenta, non è quindi un tool interattivo. Dato che il numero di cammino possibili può risultare molto grande, la simulazione di tutti i cammini risulta un’operazione intrattabile. Questo implica che limitare il numero di cammini percorribili, limita di conseguenza anche il numero di errori rilevati </li></ul><ul><li>È incompleto nel considerare gli errori che possono essere rilevati. Non tutti gli errori vengono rilevati (espandi). </li></ul><ul><li>Non c’è la possibilità di limitare il codice da analizzare. </li></ul><ul><li>La creazione di modelli per funzioni di cui non si dispone il codice (es. librerie dinamiche), risulta difficoltosa. </li></ul>
12.
Conclusioni <ul><li>È uno strumento indispensabile durante lo sviluppo di un’applicazione. </li></ul><ul><li>Molto utile quando si vogliono scoprire dei bug che sarebbero stati di difficile individuazione anche con debugger che usano test cases. </li></ul><ul><li>La possibilità di vedere il cammino che genera l’errore è essenziale per l’usabilità del tool. </li></ul><ul><li>La possibilità di filtrare i noise errors , e la possibilità di parametrizzare il numero di cammini visitati nonché il numero di volte che si devono eseguire le funzioni ricorsive, sono di vitale importanza. </li></ul>
13.
References <ul><li>A Static Analyzer for Finding Dynamic Programming Errors, William R. Bush, Jonathan D. Pincus, David J. Sielaff, Intrinsa Corporation, Mountain View, CA, USA </li></ul><ul><li>CMSC 631 Program Analysis and Understanding, Department of Computer Science, University of Maryland </li></ul>