Domanda

Come ho capito dalla mia lettura, il comportamento indefinito è il risultato di lasciare al compilatore diverse alternative non identiche in fase di compilazione.Tuttavia, ciò non significherebbe che se si dovesse seguire una rigorosa pratica di codifica (come mettere ogni assegnazione e ogni uguaglianza in un'istruzione separata, debug e commenti adeguati) allora non dovrebbe rappresentare un problema significativo nel trovare la fonte dell'indefinito -comportamento.

Inoltre, per ogni errore che si verifica, se identifichi il codice, dovresti sapere quali istruzioni possono essere utilizzate al posto di quella particolare istruzione, giusto?

MODIFICARE:Non mi interessano i posti in cui hai scritto codice che non intendevi scrivere.Sono interessato agli esempi in cui il codice valido secondo la logica matematica non funziona.

Inoltre, considero "buona pratica di codifica" commenti informativi forti ogni poche righe, rientro corretto e dump del debug su base regolare.

È stato utile?

Soluzione

Il comportamento indefinito non lascia necessariamente il compilatore con più alternative.Più comunemente si tratta semplicemente di fare qualcosa che non ha senso.

Ad esempio, prendi questo codice:

int arr[2];
arr[200] = 42;

questo è un comportamento indefinito.Non è che al compilatore siano state fornite più alternative tra cui scegliere.è solo che quello che sto facendo non ha senso.Idealmente, non dovrebbe essere consentito in primo luogo, ma senza un controllo di runtime potenzialmente costoso, non possiamo garantire che qualcosa di simile non si verifichi nel nostro codice.Quindi in C++ la regola è semplicemente che il linguaggio specifica solo il comportamento di un programma che si attiene alle regole.Se fa qualcosa di errato come nell'esempio sopra, è semplicemente non definito cosa dovrebbe succedere.

Ora, immagina come rileverai questo errore.Come emergerà?Potrebbe Mai sembrano causare problemi.Forse ci capita semplicemente di scrivere nella memoria che è mappata al processo (quindi non riceviamo una violazione di accesso), ma non viene mai utilizzata in altro modo (quindi nessun'altra parte del programma leggerà il nostro valore spazzatura o sovrascriverà ciò che abbiamo scritto ).Allora sembrerà che il programma sia privo di bug e funzioni perfettamente.

Oppure potrebbe colpire un indirizzo che non è nemmeno mappato nel nostro processo.Quindi il programma si bloccherà immediatamente.

Oppure potrebbe colpire un indirizzo mappato sul nostro processo, ma ad un certo punto dopo verrà utilizzato per qualcosa.Quindi tutto ciò che sappiamo è che prima o poi la funzione che legge da quell'indirizzo assumerà un valore inaspettato e si comporterà in modo strano.Quella parte è facile da individuare nel debugger, ma non ci dice nulla Quando o da Dove è stato scritto quel valore spazzatura.Quindi non esiste un modo semplice per risalire all'origine dell'errore.

Altri suggerimenti

Innanzitutto, alcune definizioni dallo standard C++03:

1.3.5 comportamento definito dall'implementazione

Comportamento, per una struttura di programma ben formata e dati corretti, che dipende dall'implementazione e che ciascuna implementazione deve documentare

1.3.12 comportamento indefinito

Comportamento che potrebbe verificarsi in seguito all'utilizzo di un costrutto di programma errato o di dati errati, per il quale la presente norma internazionale non impone requisiti.Si può prevedere un comportamento indefinito anche quando la presente norma internazionale omette la descrizione di qualsiasi definizione o comportamento esplicito.

1.3.13 comportamento non specificato

Comportamento, per un costrutto di programma ben formato e dati corretti, che dipende dall'implementazione.Non è necessario che l'implementazione documenti quale comportamento si verifica.

Nonostante comportamento non specificato potrebbe chiamarsi UB, non l'ho mai visto, e UB significa sempre comportamento indefinito. In tutto lo standard ci sono affermazioni simili a "fare X è un comportamento indefinito", ma a volte ti imbatti in un caso che semplicemente non è coperto.

Per mettere la definizione in un altro modo, se hai qualche comportamento indefinito da qualche parte, allora tutte le scommesse sono chiuse.Per quanto riguarda lo standard, il tuo programma potrebbe fare qualsiasi cosa, dall'invitare tua suocera per il fine settimana del SuperBowl a eseguire nethack.A causa della natura stessa di UB non puoi testarlo e non puoi aspettarti alcun aiuto dal compilatore.(Sebbene per alcuni errori banali e comuni i compilatori generalmente producono diagnostica.)

Di solito qualcosa viene definito come UB perché semplicemente non ha senso logico (ad es.accedendo a un array fuori dai limiti), ma spesso anche perché richiederebbe all'implementazione di fare troppo lavoro per prevenirlo, spesso in fase di esecuzione.Ricorda che C++ deriva da C e essere in grado di produrre programmi altamente ottimizzati è uno degli obiettivi principali di entrambi i linguaggi.A tal fine, i linguaggi demandano al programmatore la verifica della correttezza del codice in queste situazioni, legate al principio "non paghi per quello che non usi".

Quindi, in definitiva, UB è pessima, pessima;Evitalo a tutti i costi.Tuttavia, la parte difficile dell'UB non è sapere di cosa si tratta o in quali circostanze si verifica;la parte difficile è riconoscere quando invochi UB.Per esempio:

std::string s = "abc";
char& c = s[0];
cout.write(s.data(), s.length());
c = '-';

Sembra perfettamente ragionevole, vero?No, questa è UB, per ora funzionerà come previsto su tutte le implementazioni più diffuse.

Non sono sicuro se c'è una definizione formale di "comportamento indefinito", ma a seguito di buoni standard di codifica in grado di ridurre l'ambiguità e portare a un minor numero di difetti di compilazione e di esecuzione.

Tuttavia, ottenere due programmatori di accordo su ciò che "buoni standard di codifica" è un processo complicato e soggetto a errori.

Per la seconda domanda, sì compilatori in genere in uscita un codice di errore che è possibile utilizzare per risolvere il problema

  

Da quanto ho capito dalla mia lettura, non definito, il comportamento è il risultato di lasciare il compilatore con diverse alternative non identici in fase di compilazione.

Mentre quello può essere una fonte di comportamento non definito, si sta parlando troppo astrattamente. Avete bisogno di un esempio specifico di cosa si intende per "alternative non identici in fase di compilazione."

Se per "seguire la pratica di codifica rigorosa," intendi non utilizzare la logica che si traduce in un comportamento indefinito, allora sì (perché non ci sarebbe alcun comportamento non definito). Rintracciare un bug a causa del comportamento non definito può o non può essere più facile di monitoraggio di quello causato da un errore logico.

Si noti che il codice che si traduce in "un comportamento indefinito" è ancora codice legale C ++. Ritengo che una classe di codice / logica che deve solo molto raramente essere utilizzata, quando che "il comportamento indefinito" è prevedibile per un dato programma in una determinata piattaforma con una data implementazione. Troverete casi che ciò che il linguaggio considera "un comportamento indefinito" verrà infatti definita per un particolare ambiente / insieme di vincoli.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top