Programmi teoricamente privi di bug


12

Ho letto molti articoli che affermano che il codice non può essere privo di bug e parlano di questi teoremi:

In realtà il teorema di Rice sembra un'implicazione del problema di arresto e il problema di arresto è in stretta relazione con il teorema di incompletezza di Gödel.

Ciò implica che ogni programma avrà almeno un comportamento indesiderato? O significa che non è possibile scrivere codice per verificarlo? Che dire del controllo ricorsivo? Supponiamo che io abbia due programmi. Entrambi hanno dei bug, ma non condividono lo stesso bug. Cosa succederà se li eseguo contemporaneamente?

E naturalmente la maggior parte delle discussioni parlava delle macchine di Turing. Che dire dell'automazione lineare (computer reali)?


10
Sono abbastanza sicuro che questo programma Python fa tutto ciò che deve fare e non di più: print "Hello, World!"... puoi essere un po 'più chiaro?
durron597,

2
@ durron597: esiste un mercato per questo software? Ciao stampanti mondo, versione ricaricata? Ora con più hellos e più mondi?
JensG,

1
@Phoshi faugh. È abbastanza possibile scrivere un programma abbastanza semplice (diciamo, usando i fili su una breadboard) da poter vedere tutto l'ambito del processo tutto in una volta senza errori. Stai attaccando i dettagli del mio commento senza affrontare il mio punto principale, che è che è possibile scrivere programmi estremamente semplici senza bug.
durron597,

2
@Phoshi "Dimostra che il tuo interprete python non ha bug." I bug nell'implementazione di Python non rendono il programma sbagliato. Il programma è corretto se fa ciò che si suppone dato che l'implementazione di Python è conforme alle specifiche del linguaggio. Qualsiasi prova assume alcune cose come assiomi: per esempio, dovrete presumere che l'universo continuerà ad esistere per tutta l'esecuzione del programma. Se CPython ha un bug, il risultato potrebbe essere sbagliato, ma l'errore non era nel programma.
Doval,

11
Nessuno di questi teoremi ha nulla a che fare con i bug o l'esistenza di programmi senza bug. Sono teoremi su quali domande rispondono per calcolo. Questi teoremi mostrano che ci sono alcuni problemi che non possono essere calcolati e alcune proposizioni matematiche che non possono essere né dimostrate né smentite, ma certamente non dicono che tutti i programmi hanno dei bug o che determinati programmi non possono essere dimostrati corretti.
Charles E. Grant,

Risposte:


18

Non è così tanto che i programmi non possono essere privi di bug; è che è molto difficile dimostrare che lo sono, se il programma che stai cercando di dimostrare non è banale.

Non per mancanza di tentativi, intendiamoci. I sistemi di tipo dovrebbero fornire qualche garanzia; Haskell ha un sistema di tipo altamente sofisticato che lo fa, fino a un certo punto. Ma non puoi mai rimuovere tutta l'incertezza.

Considera la seguente funzione:

int add(int a, int b) { return a + b; }

Cosa potrebbe andare storto con questa funzione? So già cosa stai pensando. Diciamo che abbiamo coperto tutte le basi, come il controllo del trabocco, ecc. Cosa succede se un raggio cosmico colpisce il processore, facendolo eseguire

LaunchMissiles();

anziché?

OK, forse è un po 'inventato. Ma anche funzioni semplici come la addfunzione sopra devono operare in ambienti in cui il processore cambia costantemente contesti, passando da thread multipli e core. In un ambiente del genere, tutto può succedere. Se ne dubiti, considera che la RAM è affidabile, non perché è priva di errori, ma perché ha un sistema integrato per correggere gli errori di bit che inevitabilmente si verificano.

So cosa stai pensando. "Ma sto parlando di software, non di hardware."

Esistono molte tecniche che possono migliorare il livello di confidenza che il software funziona nel modo previsto. La programmazione funzionale è una di queste. La programmazione funzionale ti consente di ragionare meglio sulla concorrenza. Ma la programmazione funzionale non è una prova, non più di quanto lo siano i test unitari.

Perché? Perché hai queste cose chiamate casi limite.

E una volta che vai oltre la semplicità return a + b, diventa notevolmente difficile dimostrare la correttezza di un programma.

Ulteriori letture
scrivono la cosa giusta
The Ariane 5 Explosion


6
Considera la funzione totalmente corretta per il tipo: int add(int a, int b) { return a - b; }...
Donal Fellows

@DonalFellows: Questo è esattamente il motivo per cui ho incluso il link sull'Ariane 5.
Robert Harvey,

2
@DonalFellows - La caratterizzazione matematica non risolve il problema, lo sposta solo altrove. Come dimostrate che il modello matematico rappresenta effettivamente il bisogno del cliente?
mouviciel,

1
@JohnGaughan Questo presuppone interdipendenze tra i moduli. Dati i moduli che sono stati dimostrati corretti e si sono dimostrati indipendenti l'uno dall'altro, è possibile comporli ricorsivamente in moduli più grandi che sono anche noti per essere corretti e indipendenti all'infinito.
Doval,

1
@JohnGaughan Se l'integrazione dei moduli causa bug, non sei riuscito a dimostrare che sono indipendenti. Costruire nuove prove a partire da prove consolidate non è più difficile della costruzione di prove a partire da assiomi. Se la matematica diventasse esponenzialmente più difficile in quel modo, i matematici sarebbero fregati. Potresti avere dei bug nei tuoi script di build, ma questo è un programma separato. Non c'è nessun elemento misterioso che va storto quando si tenta di comporre le cose, ma a seconda del numero di effetti collaterali può essere difficile provare che non esiste uno stato condiviso.
Doval,

12

Innanzitutto, stabiliamo in quale contesto desideri discuterne. Le domande e risposte dei programmatori a Stack Exchange suggeriscono che molto probabilmente sei interessato all'esistenza nel mondo reale di strumenti / linguaggi piuttosto che a risultati teorici e teoremi di informatica .

Ho letto molti articoli in cui si afferma che il codice non può essere privo di bug

Spero di no, perché una simile affermazione non è corretta. Sebbene sia comunemente accettato che la maggior parte delle applicazioni su larga scala non siano prive di bug al meglio delle mie conoscenze ed esperienze.

Più comunemente accettato è che non esiste (cioè esistenza, non possibilità) uno strumento che determina perfettamente se un programma scritto in un linguaggio di programmazione completo di Turing è completamente privo di bug.

Una non-prova è un'estensione intuitiva del problema di interruzione, combinata con i dati di osservazione dell'esperienza quotidiana.

Ci fa software esistono che può fare "prove di correttezza " che verificare che un programma soddisfa le corrispondenti formali specifiche per il programma.

Ciò implica che ogni programma avrà almeno un comportamento indesiderato?

No. Sebbene sia stato riscontrato che la maggior parte delle applicazioni presenta almeno un bug o un comportamento indesiderato.

O significa che non è possibile scrivere codice per verificarlo?

No, è possibile utilizzare le specifiche formali e gli assistenti di prova per verificare di seguire le specifiche , ma poiché l'esperienza ha dimostrato che possono ancora esistere errori nel sistema complessivo, come fattori al di fuori delle specifiche: il traduttore del codice sorgente e l'hardware, e più spesso vengono commessi errori nelle specifiche stesse.

Per maggiori dettagli cruenti, vedi Coq è un tale strumento / linguaggio / sistema.

Che dire del controllo ricorsivo?

Non lo so. Non ne ho familiarità e non sono sicuro che si tratti di un problema di calcolabilità o di ottimizzazione del compilatore.


1
+1 per essere stato il primo a parlare di specifiche formali e assistenti di prova. Questo è un punto cruciale, che manca nelle risposte precedenti.
Arseni Mourzenko,

6

Voglio chiedere, implica che ogni codice avrà almeno un comportamento indesiderato?

No. I programmi corretti possono essere e sono scritti. Intendiamoci, un programma può essere corretto, ma la sua esecuzione potrebbe non riuscire a causa, ad esempio, di circostanze fisiche (come ha scritto l'utente Robert Harvey nella sua risposta qui ), ma questa è una questione distinta: il codice di quel programma è ancora corretto. Per essere più precisi, l' errore non è causato da un errore o un errore nel programma stesso, ma nella macchina sottostante che lo esegue (*).

(*) Prendo in prestito definizioni di guasto , errore e guasto dal campo di affidabilità come, rispettivamente, un difetto statico, uno stato interno errato e un comportamento osservato esterno errato secondo le sue specifiche (vedere <qualsiasi documento di quel campo>) .

Oppure, significa che non sono in grado di scrivere codice, che lo controllerà?

Fare riferimento al caso generale nella dichiarazione sopra e si è corretti.

Potresti essere in grado di scrivere un programma che controlla se un programma X specifico è corretto. Ad esempio, se si definisce un programma "ciao mondo" come uno con due istruzioni in sequenza, vale a dire print("hello world")e exit, è possibile scrivere un programma che controlla se il suo input è un programma composto da queste due istruzioni in sequenza, segnalando quindi se è un programma "ciao mondo" corretto o no.

Quello che non puoi fare usando le formulazioni attuali è scrivere un programma per verificare se qualche programma arbitrario si interrompe, il che implica l'impossibilità di verificare la correttezza nei casi generali.


4

L'esecuzione di due o più varianti dello stesso programma è una nota tecnica di tolleranza agli errori chiamata programmazione della variante N (o versione N). È un riconoscimento della presenza di bug nel software.

Di solito queste varianti sono codificate da diversi team di sviluppo, utilizzando diversi compilatori, e talvolta vengono eseguite su CPU diverse con sistemi operativi diversi. I risultati vengono votati prima di essere inviati all'utente. Boeing e Airbus adorano questo tipo di architettura.

Rimangono due collegamenti deboli, che portano a bug di modalità comuni:

  • C'è solo una specifica.
  • il sistema di voto è unico o complesso.

5
Credo che la NASA o altri programmi spaziali abbiano suggerito che la variante N soffre del problema che troppo spesso i programmatori pensano allo stesso modo e quindi finiscono per scrivere autonomamente vicino a programmi equivalenti con difetti comuni quando il difetto è oltre il livello più banale. Ad esempio, fai riferimento alle stesse informazioni di riferimento (vedi bug di vecchia data nella ricerca binaria ), tende ad usare gli stessi algoritmi e fa gli stessi tipi di errori.
mctylr,

@mctylr - È un ottimo punto. Ma in realtà, fino a poco tempo fa, non c'era abbastanza spazio in memoria per memorizzare più di una variante di un software su un veicolo spaziale. La loro risposta è test, test, test, risciacquo, ripetizione.
mouviciel,

Il programma di navetta spaziale utilizzava una configurazione di votazione di tre sistemi indipendenti. Qualsiasi voto dissenziente significava (o, in realtà, suggeriva) che il sistema non era più corretto e veniva messo offline.

4

Un programma ha alcune specifiche e viene eseguito in alcuni ambienti.

(l'esempio del raggio cosmico in altre risposte che cambiano addin FireMissiles potrebbe essere considerato parte dell '"ambiente")

Supponendo che sia possibile specificare formalmente il comportamento previsto del programma (ovvero la sua specifica) e il suo ambiente, a volte si potrebbe dimostrare formalmente che il programma è in quel preciso senso privo di bug (quindi il suo comportamento o output rispetta la formalizzazione delle sue specifiche nella formalizzazione del suo ambiente).

In particolare, è possibile utilizzare analizzatori di sorgenti statiche audio, ad esempio Frama-C .

(ma l'attuale stato dell'arte di tali analizzatori non consente l'analisi dell'intero programma e la prova di programmi su larga scala come il compilatore GCC o il browser Firefox o il kernel Linux; e la mia convinzione è che tali prove non accadranno nella mia vita Sono nato nel 1959)

Tuttavia, ciò che hai dimostrato è il comportamento corretto del programma con alcune specifiche particolari in alcuni ambienti (classi di).

In pratica, potresti (e la NASA o l'ESA probabilmente vogliono) dimostrare che alcuni software per veicoli spaziali sono "privi di bug" con specifiche precise e formalizzate. Ma ciò non significa che il tuo sistema si comporterà sempre come desideri.

In parole più semplici, se il tuo robot spaziale incontra qualche ET e non lo hai specificato, non c'è modo di far comportare il tuo robot come vuoi davvero ....

Leggi anche le voci del blog di J.Pitrat .

A proposito, il problema di Halting o il teorema di Gödel probabilmente si applica anche al cervello umano o persino alla specie umana.


Forse un esempio migliore di un SEU cambiare la chiamata a Adda LaunchMissilessarebbe un SEU cambiando qualche valore dei dati che alla fine si traduce in una chiamata errata a LaunchMissiles. Le SEU rappresentano un problema con i computer che vanno nello spazio. Questo è il motivo per cui i moderni veicoli spaziali spesso pilotano più computer. Ciò aggiunge una nuova serie di problemi, gestione della concorrenza e ridondanza.
David Hammen,

3

Ciò implica che ogni programma avrà almeno un comportamento indesiderato?

No.

Il problema di arresto dice che è impossibile scrivere un programma che verifica se ogni programma si interrompe in un tempo limitato. Ciò non significa che sia impossibile scrivere un programma in grado di classificare alcuni programmi come fermi, altri come non-stop. Ciò significa che ci saranno sempre alcuni programmi che un analizzatore in pausa non può classificare in un modo o nell'altro.

I teoremi di incompletezza di Gödel hanno un'area grigia simile a loro. Dato un sistema matematico di sufficiente complessità, ci saranno alcune affermazioni fatte nel contesto di quel sistema la cui veridicità non può essere valutata. Ciò non significa che i matematici debbano rinunciare all'idea della prova. La prova rimane la pietra angolare della matematica.

Alcuni programmi possono essere dimostrati corretti. Non è facile, ma può essere fatto. Questo è l'obiettivo della dimostrazione del teorema formale (una parte dei metodi formali). I teoremi di incompletezza di Gödel colpiscono qui: non tutti i programmi possono essere dimostrati corretti. Ciò non significa che sia assolutamente inutile usare metodi formali perché alcuni programmi possono effettivamente essere dimostrati formalmente corretti.

Nota: i metodi formali precludono la possibilità che un raggio cosmico colpisca il processore ed esegua launch_missiles()invece di a+b. Analizzano i programmi nel contesto di una macchina astratta piuttosto che macchine reali che sono soggette a sconvolgimenti di singoli eventi come il raggio cosmico di Robert Harvey.


1

Ci sono molte buone risposte qui, ma tutte sembrano aggirare il punto critico, che è questo: tutti quei teoremi hanno una struttura simile e dicono cose simili, e ciò che dicono non è "è impossibile probabilmente scrivere correttamente programmi"(per un valore specifico di 'corretto' e 'programma' che varia a seconda dei casi), ma quello che fanno dire è 'è impossibile impedire che qualcuno a scrivere un programma non corretta che non possiamo dimostrare di essere corretto' ( eccetera).

Prendendo l'esempio specifico del problema dell'arresto, la differenza diventa più chiara: ovviamente ci sono programmi che si fermano in modo dimostrabile e altri programmi che non si fermano mai. Il fatto che esista una terza classe di programmi il cui comportamento non può essere determinato in entrambi i modi non è un problema se tutto ciò che vogliamo fare è scrivere un programma in grado di fermare, poiché possiamo semplicemente evitare di scrivere un programma che appartiene a quella classe.

Lo stesso vale per il teorema di Rice. Sì, per qualsiasi proprietà non banale di un programma possiamo scrivere un programma che non può né avere quella proprietà dimostrata vera né falsa; possiamo anche evitare di scrivere un tale programma perché siamo in grado di determinare se un programma è dimostrabile.


0

La mia risposta sarà dalla prospettiva del mondo reale e dalle sfide che ogni team di sviluppo deve affrontare. Quello che vedo in questa domanda e molte risposte riguarda davvero il controllo dei difetti.

Il codice può essere privo di bug. Prendi uno qualsiasi degli esempi di codice "Hello World" per qualsiasi linguaggio di programmazione ed eseguilo sulla piattaforma in cui è previsto e funzionerà in modo coerente e produrrà i risultati desiderati. Termina qualsiasi teoria sull'impossibilità che il codice sia privo di bug.

I potenziali bug arrivano quando la logica diventa più complessa. Il semplice esempio di Hello World non ha logica e fa sempre la stessa cosa statica. Non appena si aggiunge un comportamento dinamico basato sulla logica è ciò che introduce la complessità che porta ai bug. La logica stessa può essere difettosa oppure i dati immessi nella logica possono variare in un modo che la logica non gestisce.

Un'applicazione moderna dipende anche da librerie di runtime, CLR, middleware, database, ecc. Che, pur risparmiando tempo di sviluppo complessivo, sono anche livelli in cui possono esistere bug all'interno di tali livelli che non vengono rilevati attraverso lo sviluppo e il test UAT e nella produzione.

Infine, la catena di app / sistemi in cui l'applicazione consuma i dati che alimentano la sua logica sono tutte le fonti di potenziali bug o all'interno della loro logica, o all'interno del software impila i percorsi logici in cima o i sistemi a monte che consuma i dati.

Gli sviluppatori non hanno il controllo al 100% di ogni elemento mobile che supporta la logica della loro applicazione. In realtà, non abbiamo molto controllo. Questo è il motivo per cui i test unitari sono importanti e la configurazione e la gestione delle modifiche sono processi importanti che non dobbiamo ignorare o essere pigri / sciatti.

Inoltre, gli accordi documentati tra l'applicazione che consuma i dati da una fonte al di fuori del proprio controllo, che definisce il formato e le specifiche specifici per i dati trasferiti, nonché qualsiasi limite o vincolo che il sistema presume sia responsabile del sistema di origine per garantire che l'output sia all'interno quei limiti.

Nell'applicazione del mondo reale dell'ingegneria del software non sarai in grado di farlo volare spiegando al business perché teoricamente le applicazioni non possono essere prive di bug. Discussioni di questa natura tra tecnologia e impresa non accadranno mai se non a seguito di un malfunzionamento tecnologico che ha influito sulla capacità dell'azienda di fare soldi, impedire di perdere denaro e / o mantenere in vita le persone. La risposta a "come può accadere" non può essere "lasciami spiegare questa teoria in modo che tu capisca".

In termini di calcoli enormi che teoricamente potrebbero richiedere un'eternità per eseguire il calcolo e ottenere un risultato, un'applicazione che non può finire e restituire con un risultato - questo è un bug. Se la natura del calcolo è tale da richiedere molto tempo e un'elaborazione intensiva, prendi quella richiesta e fornisci feedback all'utente come / quando possono recuperare il risultato e dare il via ai thread paralleli per sfornare. Se ciò deve avvenire più rapidamente di quanto si possa fare su un server ed è abbastanza importante per le aziende, lo si ridimensiona su tutti i sistemi necessari. Questo è il motivo per cui il cloud è molto interessante e la capacità di far girare i nodi per iniziare a lavorare e rigirarli al termine.

Se esiste la possibilità di ottenere una richiesta che nessuna quantità di potenza di calcolo può completare, non dovrebbe rimanere in esecuzione all'infinito con un processo aziendale in attesa della risposta a ciò che l'azienda ritiene sia un problema finito.


-2

Non credo che il codice sia mai privo di bug al 100% perché il codice non è mai veramente finito. Puoi sempre migliorare ciò che scrivi.

La programmazione è un campo della scienza e della matematica, nel qual caso entrambi sono infiniti. La cosa grandiosa di essere uno sviluppatore è che il nostro lavoro è infinito.

Ci sono più di mille modi per scrivere una singola riga di codice. L'idea è di scrivere la versione più ottimizzata di quella riga di codice, ma potrebbe non essere priva di bug. Bug free si riferisce all'idea che il tuo codice è infrangibile e tutto il codice può essere infranto in una certa misura o metodo.

Quindi il codice può essere efficiente? Sì.
Il codice può essere ottimizzato all'infinito? Sì.
Il codice può essere privo di bug? No, semplicemente non hai ancora trovato un modo per romperlo.
Detto questo, se ti sforzi di migliorare te stesso e le tue pratiche di scrittura del codice, il tuo codice sarà difficile da infrangere.


questo post è piuttosto difficile da leggere (wall of text). Ti dispiacerebbe modificarlo in una forma migliore?
moscerino del
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.