Verifica formale del programma in pratica


66

Come ingegnere del software, scrivo molto codice per i prodotti industriali. Elementi relativamente complicati con classi, thread, alcuni sforzi di progettazione, ma anche alcuni compromessi per le prestazioni. Faccio molti test e sono stanco dei test, quindi mi sono interessato a strumenti di dimostrazione formale, come Coq, Isabelle ... Potrei usare uno di questi per dimostrare formalmente che il mio codice è privo di bug ed essere fatto con esso? - ma ogni volta che controllo uno di questi strumenti, vado via senza essere convinto che siano utilizzabili per l'ingegneria del software di tutti i giorni. Ora, potrei essere solo io, e sto cercando suggerimenti / opinioni / idee a riguardo :-)

In particolare, ho l'impressione che per far funzionare uno di questi strumenti per me sarebbe necessario un enorme investimento per definire correttamente al prover gli oggetti, i metodi ... del programma in esame. Mi chiedo quindi se il prover non si limiterebbe a rimanere senza vapore, date le dimensioni di tutto ciò che dovrebbe affrontare. O forse dovrei sbarazzarmi degli effetti collaterali (quegli strumenti prover sembrano fare davvero molto bene con i linguaggi dichiarativi), e mi chiedo se ciò comporterebbe un "codice comprovato" che non potrebbe essere usato perché non sarebbe veloce o abbastanza piccolo. Inoltre, non ho il lusso di cambiare la lingua con cui lavoro, deve essere Java o C ++: non posso dire al mio capo che sto per scrivere codice in OXXXml da ora in poi, perché è l'unica lingua in che posso dimostrare la correttezza del codice ...

Qualcuno con più esperienza negli strumenti di correzione formale può commentare? Ancora una volta - ADORO usare uno strumento prover formale, penso che siano fantastici, ma ho l'impressione che si trovino in una torre d'avorio che non riesco a raggiungere dal modesto fossato di Java / C ++ ... (PS: I anche LOVE Haskell, OCaml ... non ho un'idea sbagliata: sono un fan dei linguaggi dichiarativi e delle prove formali, sto solo cercando di vedere come potrei realisticamente renderlo utile all'ingegneria del software)

Aggiornamento: poiché questo è abbastanza ampio, proviamo le seguenti domande più specifiche: 1) ci sono esempi di utilizzo dei tester per dimostrare la correttezza dei programmi Java / C ++ industriali? 2) Coq sarebbe adatto a quel compito? 3) Se Coq è adatto, devo prima scrivere il programma in Coq, quindi generare C ++ / Java da Coq? 4) Questo approccio potrebbe gestire threading e ottimizzazioni delle prestazioni?


3
Capisco e apprezzo il tuo problema, ma non capisco di cosa si occupi questa domanda (come post SE). Discussione? Esperienza? Nessuno dei due è adatto per SE. Il "Qualunque cosa posso fare?" il tono mi fa sentire che anche questa è una domanda troppo ampia.
Raffaello

3
Vedo ... Accetto che questa domanda non sia stata formulata chiaramente. Quindi, diciamo: 1) ci sono esempi di utilizzo dei tester per dimostrare la correttezza dei programmi industriali Java / C ++? 2) Coq sarebbe adatto a quel compito? 3) Se Coq è adatto, devo prima scrivere il programma in Coq, quindi Coq dovrebbe generare C ++ / Java da quello? 4) Questo approccio potrebbe far fronte al threading e alle ottimizzazioni delle prestazioni?
Frank,

2
Quindi sono quattro domande, quindi. 1) probabilmente sta meglio sull'ingegneria del software dal momento che è improbabile incontrare qui (molti) professionisti del settore. 2) ha un sapore un po 'soggettivo, ma qui possiamo avere persone che possono offrire una prospettiva obiettiva. 3) è, per quanto posso dire, completamente soggettivo. 4) È una bella domanda per questo sito. In sintesi: separa le tue domande, vai al Software Engineering con il primo e pensa attentamente se puoi aspettarti una risposta obiettiva (!) Qui (!) Prima di pubblicare 2).
Raffaello

10
Stai descrivendo il sogno di una verifica formale, ma siamo molto lontani dall'essere lì. AFAIK, la verifica del programma è un'attività non di routine e si applica solo a programmi molto semplici. Detto questo, penso che questa domanda sia perfetta per il sito e apprezzerei qualcuno della zona che ammette i limiti del proprio campo, spiegando lo stato dell'arte e i limiti (forse collegando un sondaggio ).
Yuval Filmus,

9
Il problema con la verifica dei programmi C ++ è che C ++ non è un linguaggio ben definito. Non credo che la verifica su larga scala sia possibile fino a quando molte parti dei sistemi software (sistema operativo, librerie, linguaggi di programmazione) non verranno effettivamente ridisegnate per supportare la verifica. Come è noto, non puoi semplicemente scaricare 200000 righe di codice su qualcuno e dire "verifica!". Devi verificare e scrivere il codice insieme e devi adattare le tue abitudini di programmazione al fatto che stai anche verificando.
Andrej Bauer,

Risposte:


35

Proverò a dare una risposta concisa ad alcune delle tue domande. Tieni presente che questo non è strettamente il mio campo di ricerca, quindi alcune delle mie informazioni potrebbero essere obsolete / errate.

  1. Esistono molti strumenti appositamente progettati per dimostrare formalmente le proprietà di Java e C ++.

    Tuttavia, devo fare una piccola digressione qui: cosa significa dimostrare la correttezza di un programma? Il controllo del tipo Java dimostra una proprietà formale di un programma Java, vale a dire che alcuni errori, come l'aggiunta di a floate an int, non possono mai verificarsi! Immagino che tu sia interessato a proprietà molto più forti, vale a dire che il tuo programma non può mai entrare in uno stato indesiderato, o che l'output di una determinata funzione è conforme a una determinata specifica matematica. In breve, esiste un ampio gradiente di ciò che può significare "dimostrare un programma corretto", da semplici proprietà di sicurezza a una prova completa che il programma soddisfa una specifica dettagliata.

    Ora suppongo che tu sia interessato a dimostrare forti proprietà sui tuoi programmi. Se sei interessato alle proprietà di sicurezza (il tuo programma non può raggiungere un determinato stato), in generale sembra che l'approccio migliore sia il controllo del modello . Tuttavia, se si desidera specificare completamente il comportamento di un programma Java, la soluzione migliore è utilizzare un linguaggio di specifica per quella lingua, ad esempio JML . Esistono tali linguaggi per specificare il comportamento dei programmi C, ad esempio ACSL , ma non conosco C ++.

  2. Una volta che hai le tue specifiche, devi dimostrare che il programma è conforme a quelle specifiche.

    Per questo è necessario uno strumento che abbia una comprensione formale sia della specifica che della semantica operativa del proprio linguaggio (Java o C ++) al fine di esprimere il teorema di adeguatezza , vale a dire che l'esecuzione del programma rispetta le specifiche.

    Questo strumento dovrebbe anche permetterti di formulare o generare la prova di quel teorema. Ora entrambi questi compiti (specificare e provare) sono piuttosto difficili, quindi sono spesso separati in due:

    • Uno strumento che analizza il codice, le specifiche e genera il teorema di adeguatezza. Come ha detto Frank, Krakatoa è un esempio di tale strumento.

    • Uno strumento che dimostra il teorema (i), automaticamente o interattivamente. Coq interagisce con Krakatoa in questo modo e ci sono alcuni potenti strumenti automatizzati come Z3 che possono anche essere usati.

    Un punto (minore): ci sono alcuni teoremi che sono troppo difficili da dimostrare con metodi automatizzati e che i dimostratori di teoremi automatici hanno occasionalmente dei bug di solidità che li rendono meno affidabili. Questa è un'area in cui Coq brilla in confronto (ma non è automatico!).

  3. Se vuoi generare il codice Ocaml, allora scrivi prima in Coq (Gallina), quindi estrai il codice. Tuttavia, Coq è terribile nel generare C ++ o Java, se è persino possibile.

  4. Gli strumenti di cui sopra possono gestire problemi di threading e prestazioni? Probabilmente no, i problemi di prestazioni e threading sono gestiti meglio da strumenti appositamente progettati, in quanto sono problemi particolarmente difficili. Non sono sicuro di avere degli strumenti da raccomandare qui, anche se il progetto PolyNI di Martin Hofmann sembra interessante.

In conclusione: la verifica formale dei programmi Java e C ++ del "mondo reale" è un campo ampio e ben sviluppato, e Coq è adatto a parti di tale compito. Puoi trovare una panoramica di alto livello qui per esempio.


Grazie per questo post e i riferimenti che hai aggiunto. IMHO, l'obiettivo per gli ingegneri del software è di essere in grado di rilasciare rapidamente sistemi che 1) forniranno sempre risultati corretti, 2) non falliranno mai. Potrei vedere un problema di regressione qui, dove potresti voler dimostrare che la specifica stessa è "senza bug" :-) un po 'come cercare di definire "vera proposizione di una lingua" con un meta-linguaggio, quindi necessitando di un'altra meta- lingua per quello, poi un altro ...
Frank

6
Il problema è che ciò che l'utente "vuole" di solito non è espresso in un linguaggio formale! Generalmente non esiste una risposta formale alla domanda: "questa specifica formale è conforme alla mia idea informale?". È possibile testare una specifica formale e dimostrare che ha alcune proprietà matematiche, ma alla fine è necessario collegare la matematica al mondo reale, che è un processo non formale.
codice

Sì, certo - ho sempre capito che i metodi formali potevano partire solo da un punto ben definito. Se tale specifica è conforme o meno ai bisogni consci / inconsci / non scoperti degli utenti della vita reale è un altro problema, non risolvibile con metodi formali (ma sicuramente un problema per gli ingegneri).
Frank,

Un teorema è per definizione una proposta dimostrata. Quindi, probabilmente non intendi "dimostrare il teorema".
nbro,

@nbro Wikipedia sembra essere d'accordo con te. Mathworld, tuttavia, definisce un teorema come una proposizione che " può essere dimostrata vera mediante operazioni matematiche accettate". In questo caso, dare prove dei teoremi non è solo possibile, ma necessario per giustificare chiamarli così! :) (questo è un contrappeso, ovviamente)
codice

15

Vorrei menzionare tre notevoli applicazioni di metodi formali / strumenti di verifica formale nell'industria o in sistemi reali non banali. Nota che ho poca esperienza su questo argomento e li imparo solo leggendo articoli.

  1. Lo strumento open source Java Pathfinder (in breve JPF) rilasciato dalla NASA nel 2005 è un sistema per verificare i programmi eseguibili bytecode Java (vedi Java Pathfinder @ wiki ). È stato utilizzato per rilevare incoerenze nel software esecutivo per K9 Rover presso la NASA Ames.

  2. Questo documento: L' uso del controllo del modello per trovare gravi errori del file system @ OSDI'04 mostra come utilizzare il controllo del modello per trovare errori gravi nei file system. Un sistema chiamato FiSC viene applicato a tre file system ampiamente utilizzati e ampiamente testati: ext3, JFS e ReiserFS e vengono rilevati 32 bug gravi. Ha vinto il Best Paper Award.

  3. Questo documento: In che modo Amazon Web Services utilizza i metodi formali @ CACM'15 descrive come AWS applica i metodi formali ai suoi prodotti come S3, DynamoDB, EBS e Gestione blocchi distribuiti interni. Si concentra sullo strumento TLA + di Lamport . A proposito, Lamport ha usato intensamente la propria cassetta degli attrezzi TLA. Dà spesso una verifica (abbastanza completa) formale in TLA degli algoritmi / teoremi proposti da lui stesso (così come coautori) in appendici ai documenti.


4

Una specifica formale di un programma è (più o meno) un programma scritto in un altro linguaggio di programmazione. Di conseguenza, la specifica includerà sicuramente i propri bug.

Il vantaggio della verifica formale è che, poiché il programma e le specifiche sono due implementazioni separate, i loro bug saranno diversi. Ma non sempre: una fonte comune di bug, casi trascurati, spesso corrisponderà. Pertanto, la verifica formale non è una panacea: può ancora mancare un numero non banale di bug.

Uno svantaggio della verifica formale è che può imporre qualcosa come il doppio del costo di implementazione, probabilmente di più (è necessario uno specialista nelle specifiche formali e è necessario utilizzare gli strumenti più o meno sperimentali che ne derivano; ciò non sarà economico ).

Immagino che impostare casi di prova e impalcature per eseguirli automaticamente sarebbe un uso migliore del tuo tempo.


Il vantaggio della verifica formale è che ... Un secondo svantaggio della verifica formale è che ... Questo è confuso.
Hengxin,

Penso che la mancata corrispondenza tra le specifiche e l'attività informale sia un problema di analisi dei requisiti software non un problema di programmazione.
Kaveh,

3

La verifica formale è ora possibile per i programmi scritti in un sottoinsieme di C ++ progettato per sistemi embedded critici per la sicurezza. Vedere http://eschertech.com/papers/CanCPlusPlusBeMadeAsSafeAsSpark.ppt per una breve presentazione e http://eschertech.com/papers/CanCPlusPlusBeMadeAsSafeAsSpark.pdf per il documento completo.


5
Grazie per i collegamenti. Almeno una breve panoramica del loro contenuto sarebbe utile, per proteggersi dal collegamento rot, soprattutto perché i tuoi collegamenti sono verso un sito Web aziendale: quelli tendono a riorganizzarsi periodicamente, uccidendo tutti i collegamenti nel sito.
David Richerby,

2

Fai alcune domande diverse. Concordo che sembra che i metodi di verifica formale per applicazioni industriali / commerciali non siano così comuni. si dovrebbe capire, tuttavia, che molti compilatori di principi di "verifica formale" sono integrati per determinare la correttezza del programma! quindi, in un certo senso, se usi un compilatore moderno, stai usando gran parte dello stato dell'arte nella verifica formale.

Dici "Sono stanco dei test" ma la verifica formale non è in realtà un sostituto per i test. in un certo senso è una variazione sui test.

Tu citi Java. ci sono molti metodi avanzati di verifica formale integrati in un programma di verifica Java chiamato FindBugs che può essere effettivamente eseguito su basi di codice di grandi dimensioni. Nota che verranno visualizzati sia "falsi positivi che falsi negativi" e i risultati devono essere rivisti / analizzati da uno sviluppatore umano. Ma nota anche se non sta rilevando veri e propri difetti funzionali, generalmente genera "antipattern" che dovrebbero essere comunque evitati nel codice.

Non fai più menzione della tua particolare applicazione se non "industriale". La verifica formale nella pratica tende a dipendere dalla particolare applicazione.

Le tecniche di verifica formale sembrano essere ampiamente utilizzate in EE per dimostrare la correttezza del circuito, ad esempio nella progettazione di microprocessori.

Ecco un esempio di un sondaggio sugli strumenti di verifica formale nel campo EE di Lars Philipson .


2
È fuorviante affermare che "molti principi di" verifica formale "sono integrati nei compilatori per determinare la correttezza del programma". Ciò a cui ti riferisci è il controllo statico del tipo che fanno alcuni compilatori, ma le proprietà verificate in questo modo sono piuttosto semplici, ad esempio evitando di aggiungere un numero e una stringa. Questo è utile, ma molto diverso da quello che di solito è sottostimato dalla "verifica formale".
Martin Berger,

2
non si riferiva specificamente al controllo del tipo statico, sebbene questo sia un esempio semplice / comune. Le tecniche di ottimizzazione del compilatore imho, che sono diffuse e avanzate, sono approssimativamente simili ai principi di verifica formale, perché coinvolgono tecniche avanzate per determinare / mostrare l'equivalenza delle varianti di programma ottimizzate. quindi sembra importante evitare qui il problema dei "traslochi mobili" e non supporre che semplicemente perché un compilatore lo fa o è integrato nel compilatore, non è una verifica formale.
vzn,

2
concordato che questa non è un'intesa comune. le tecniche di ottimizzazione stanno approssimativamente creando un modello di comportamento del programma, ad esempio un loop o una subroutine, e ottimizzando quel modello, e quindi generando un nuovo codice che è dimostrabile equivalente. quindi alcune di queste ottimizzazioni sono piuttosto sofisticate nella riorganizzazione del codice e per me fanno uso di principi di verifica formale. sembra che ci siano molti altri esempi di metodi di verifica formale nel compilatore ... la domanda originale poneva molte domande diverse, come molti hanno notato, non sto cercando di rispondere a tutte le domande in essa contenute.
vzn,

2
tra l'altro, sembrano esserci alcuni principi di verifica formale utilizzati anche in JRE, motore di runtime java, ad esempio ottimizzazione dinamica, ecc ...
vzn

3
questo è "il sogno della verifica formale" a cui fa riferimento il filmus sopra, imita un'astrazione chimerica e l'industria pragmatica / utilitaria / realistica lo riconosce in gran parte come tale. grandi basi di codice sono noti da decenni per avere intrinsecamente bug / difetti per K-linee di codice e questo sarà mai cambiare non importa come i progressi teoria / tecnologia, è un fatto di umana natura. e in effetti i teoremi matematici creati dall'uomo hanno le stesse proprietà, anche se questo non è molto apprezzato! yxy
vzn,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.