Le prove di correttezza del codice diventeranno mai mainstream? [chiuso]


14

Tutti tranne i programmi più banali sono pieni di bug e quindi tutto ciò che promette di rimuoverli è estremamente allettante. Al momento, le prove di correttezza sono codici estremamente esoterici, principalmente a causa della difficoltà di apprendere questo e dello sforzo supplementare necessario per dimostrare che un programma è corretto. Pensi che la dimostrazione del codice decollerà mai?

Risposte:


8

Non proprio in questo senso, ma la pura programmazione funzionale è buona in questo campo. Se usi Haskell, è probabile che il tuo programma sia corretto se il codice viene compilato. Tranne l'IO, un buon sistema di tipo è di grande aiuto.

Anche programmare un contratto può essere utile. Vedi Contratti Microsoft Code


6
Scusate, non ho fatto molto "mondo reale" Haskell, ma ho fatto abbastanza esercizi per molte vite. Solo perché si compila non significa che è probabile che funzioni. Rispetto ad es. Ada (scelto perché è un linguaggio imperativo tipicamente staticamente scritto), direi che Haskell è un po 'più semplice, ma soprattutto perché è più conciso (minore complessità ciclomatica). Quando si ha a che fare con la monade IO, ci sono fastidi che possono rendere Haskell più difficile da ottenere nel modo giusto - è abbastanza diverso dallo stile imperativo che ci sono cose che non possono fare in modo naturale.
Steve314,

Su "non posso fare come naturalmente", considera un ciclo "while". Sì, puoi farlo tu stesso, ma la condizione while deve essere all'interno della monade perché deve reagire agli effetti collaterali del corpo del loop. Questo non significa solo che ti è stato dato il permesso di causare effetti collaterali all'interno della condizione while, ma rende anche scomodo usare quel ciclo while. Risultato finale - in genere è più facile usare la ricorsione anche nel codice IO monade - e questo significa che devi strutturare le cose in un modo particolare.
Steve314,

14

Tutti tranne i programmi più banali

non può essere completamente verificato per essere corretto con uno sforzo ragionevole. Per qualsiasi prova formale di correttezza, è necessario almeno una specifica formale e tale specifica deve essere completa e corretta. Questo non è in genere nulla che puoi facilmente creare per la maggior parte dei programmi del mondo reale. Ad esempio, prova a scrivere una specifica del genere per qualcosa come l'interfaccia utente di questo sito di discussione e sai cosa intendo.

Qui ho trovato un bell'articolo sull'argomento:

http://www.encyclopedia.com/doc/1O11-programcorrectnessproof.html


Giusto - per qualsiasi progetto di programmazione c'è una transizione da una descrizione informale del problema a una formale (in genere, oggi, sotto forma di un programma), e questo non sta andando via.
David Thornley,

astree.ens.fr Vedi le applicazioni industriali di Astrée qui
zw324,

@ZiyaoWei: tali strumenti sono utili, ma trovano solo alcuni errori formali, non di più. Se un programma di una riga come printf("1")è corretto o meno (ad esempio perché il requisito era "stampare un numero casuale equamente distribuito da 1 a 6") non può essere deciso da un analizzatore statico.
Doc Brown,

10

Il problema con le prove formali è che sposta il problema indietro di un passo.

Dire che un programma è corretto equivale a dire che un programma fa quello che dovrebbe fare. Come definisci cosa dovrebbe fare il programma? Lo specifichi. E come definisci cosa dovrebbe fare il programma nei casi limite che le specifiche non coprono? Bene, allora devi rendere le specifiche più dettagliate.

Quindi supponiamo che le tue specifiche alla fine diventino abbastanza dettagliate da descrivere il comportamento corretto di ogni aspetto dell'intero programma. Ora hai bisogno di un modo per far capire i tuoi strumenti di prova. Quindi devi tradurre le specifiche in una sorta di linguaggio formale che lo strumento di prova possa capire ... ehi, aspetta un minuto!


2
Inoltre .. "Attenzione ai bug nel codice sopra; l'ho solo dimostrato corretto, non provato." - Donald Knuth
Brendan,

8

La verifica formale ha fatto molta strada, ma di solito gli strumenti di settore / ampiamente utilizzati sono in ritardo rispetto alle ultime ricerche. Ecco alcuni recenti sforzi in questa direzione:

Spec # http://research.microsoft.com/en-us/projects/specsharp/ Questa è un'estensione di C # che supporta i contratti di codice (condizioni pre / post e invarianti) e può utilizzare questi contratti per eseguire vari tipi di analisi statica .

Progetti simili a questo esistono per altre lingue, come JML per java, e Eiffel ha praticamente incorporato.

Andando ancora oltre, progetti come slam e blast possono essere utilizzati per verificare determinate proprietà comportamentali con annotazioni / interventi minimi del programmatore, ma non possono ancora gestire la generalità generale dei linguaggi moderni (cose come l'arraymetico di overflow / puntatore di numeri interi non sono modellati).

Credo che vedremo molte più di queste tecniche utilizzate in pratica in futuro. La barriera principale è che gli invarianti di programma sono difficili da dedurre senza annotazioni manuali e i programmatori di solito non sono disposti a fornire queste annotazioni perché farlo è troppo noioso / richiede tempo.


4

A meno che non si presenti un metodo per provare automaticamente il codice senza un esteso lavoro di sviluppo.


Considera l'argomento economico: forse è meglio che gli sviluppatori "perdano" tempo con prove di correttezza piuttosto che perdere denaro a causa di errori del software.
Andres F.

Sono d'accordo con fishtoaster, a meno che non diventi molto meno dispendioso in termini di risorse, una grande quantità di software aziendale regolare non avrà il costo / beneficio per supportare quel livello di correttezza. In un'app LOB per un pubblico in cattività, a volte il vantaggio più redditizio per i costi per quanto riguarda una segnalazione di bug è l'aggiunta di una riga alla documentazione che dice "non farlo"
Bill

3

Alcuni strumenti di metodi formali (come ad esempio Frama-C per software C incorporato critico) possono essere visti come (sorta di) fornire o almeno verificare una (correttezza) prova di un determinato software. (Frama-C verifica che un programma obbedisca alle sue specifiche formalizzate, in un certo senso, e rispetti gli invarianti esplicitamente annotati nel programma).

In alcuni settori, sono possibili tali metodi formali, ad esempio DO-178C per software critico su aeromobili civili. Quindi, in alcuni casi, tali approcci sono possibili e utili.

Naturalmente, lo sviluppo di software con meno errori è molto costoso. Ma l'approccio del metodo formale ha senso per un qualche tipo di software. Se sei pessimista, potresti pensare che il bug venga spostato dal codice alla sua specifica formale (che può avere alcuni "bug", perché la formalizzazione del comportamento previsto di un software è difficile e soggetta a errori).


3

Mi sono imbattuto in questa domanda e penso che questo link potrebbe essere interessante:

Applicazioni industriali di Astrée

Dimostrare l'assenza di RTE in un sistema utilizzato da Airbus con oltre 130K righe di codice nel 2003 non sembra essere male, e mi chiedo se ci sarà qualcuno a dire che questo non è il mondo reale.


2

No. Il proverbio comune per questo è: "In teoria, teoria e pratica sono le stesse. In pratica, no."

Un esempio molto semplice: Typos.

L'esecuzione effettiva del codice attraverso i test unitari trova queste cose quasi immediatamente e un insieme coerente di test annullerà la necessità di prove formali. Tutti i casi d'uso - buoni, cattivi, errori e casi limite - devono essere elencati nei test unitari, che finiscono come una prova migliore che il codice sia corretto rispetto a qualsiasi prova separata dal codice.

Soprattutto se i requisiti cambiano o l'algoritmo viene aggiornato per correggere un bug: è più probabile che la prova formale finisca per non essere aggiornata, come spesso accade per i commenti sul codice.


3
Sbagliato. Nessun test unitario sarà mai in grado di coprire l'intera gamma di possibili parametri. Immagina "unit test" un compilatore in questo modo, assicurandoti che la semantica non cambi passaggio.
SK-logic,

3
il test unitario non è il Santo Graal ...
Ryathal,

1
@ Winston Ewert, ci sono compilatori verificati (e molti altri assemblatori verificati). E l'hardware viene verificato formalmente molto più spesso del software. Vedi qui: gallium.inria.fr/~xleroy/publi/compiler-certif.pdf
SK-logic

1
@ SK-logic, sì, ci sono compilatori di giocattoli dimostrati corretti per scopi accademici. Ma per quanto riguarda i compilatori che le persone usano effettivamente? Sospetto che la maggior parte dei compilatori vengano controllati utilizzando varie forme di test automatizzati e quasi nessuna prova formale corretta viene eseguita.
Winston Ewert,

1
@ Winston Ewert, le prove di correttezza sono pratiche e ampiamente utilizzate nella vita reale. Ciò che non è molto pratico è la maggior parte delle lingue tradizionali moderne. Spero che si estinguano tutti, quindi il valore delle prove di correttezza aumenterà in futuro.
SK-logic,

1

Penso che i limiti imposti alle prove di correttezza a causa dell'arresto del problema potrebbero essere il più grande ostacolo alle prove di correttezza che diventano mainstream.


8
Il problema di arresto dice che non possiamo determinare se un programma arbitrario si arresta. Questi programmi possono fare cose strane, come testare ogni numero intero per vedere se è un numero primo di Mersenne. Non lo facciamo nei normali programmi!
Casebash,

1
@Casebash, la domanda è se esiste un sottoinsieme utile di programmi per il quale è possibile risolvere il problema di arresto. Questo non è affatto chiaro in entrambi i casi. Cioè possiamo limitare i nostri programmi in modo da non poter fare cose come testare tutti i numeri interi senza rovinare la nostra capacità di svolgere attività utili?
Winston Ewert,

1

È già usato da tutti. Ogni volta che usi la verifica del tipo del tuo linguaggio di programmazione, stai fondamentalmente facendo una prova matematica della correttezza del tuo programma. Funziona già molto bene: richiede solo la scelta dei tipi corretti per ogni funzione e struttura di dati che usi. Più preciso è il tipo, migliore sarà il controllo che otterrai. I tipi esistenti disponibili nei linguaggi di programmazione dispongono già di strumenti abbastanza potenti per descrivere quasi ogni possibile comportamento. Funziona in tutte le lingue disponibili. C ++ e i linguaggi statici stanno eseguendo i controlli in fase di compilazione, mentre linguaggi più dinamici come python lo fanno quando il programma è in esecuzione. Il controllo esiste ancora in tutte queste lingue. (ad esempio, c ++ supporta già il controllo degli effetti collaterali allo stesso modo di haskell,


Con il bit sugli effetti collaterali in C ++, ti riferisci alla correttezza const?
Winston Ewert,

sì, const + const membro funzione. Se tutte le funzioni del membro sono const, tutti i dati negli oggetti non sono modificabili.
tp1

Sono ancora modificabili se si utilizza mutableo const_cast. Certamente vedo la connessione che disegni lì, ma il sapore di due approcci mi sembra piuttosto diverso.
Winston Ewert,

Bene, ecco perché devi scegliere di usarlo - ci sono sempre modi per aggirarlo. Ma la parte importante è come fare in modo che i compilatori controllino i problemi nell'area.
TP1
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.