2010-07-21 12 views
7

Un'implementazione C++ conforme allo standard è in grado di implementare un comportamento definito definito dall'implementazione nello standard in modo tale che sia diverso tra le diverse esecuzioni dello stesso programma compilato una volta con gli stessi dati di input?È necessario un comportamento definito dall'implementazione per essere coerente tra le esecuzioni in C++?

Ad esempio, è un'implementazione autorizzata a dire "il comportamento è questo nei fine settimana e in caso contrario" e implementare il comportamento in base a tale affermazione?

+2

avete un esempio concreto in mente? alternativamente prenderei "implementazione definita" nel senso esattamente quello e se l'implementatore fa una garanzia di consistenza quindi aspettiamo coerenza, altrimenti tutte le scommesse sono spente – msw

+3

GCC usato per essere molto più fico con comportamento indefinito: http: //en.wikipedia .org/wiki/Undefined_behavior # Compiler_easter_eggs – sarnold

risposta

1

Attuazione comportamento definito significa

non specificata fi cato Comportamento in cui ogni implementazione documenti come è fatta la scelta

È obbligatoria per gli scrittori del compilatore per documentare il comportamento di una particolare programmazione costruire per una particolare implementazione.

..... in modo che sia diverso tra diverse esecuzioni dello stesso programma compilato una volta con gli stessi dati di input?

Nopes!

Ad esempio, è un'implementazione autorizzata a dire "il comportamento è questo nei fine settimana e che altrimenti" e implementare il comportamento in base a tale affermazione?

non sono sicuro, ma penso che la risposta è no .

+4

Non vedo perché questo non è permesso. Lo standard dice "come viene fatta la scelta", non "quale unica scelta è fatta". – sharptooth

+3

Per come la vedo io, la definizione del comportamento definito dall'implementazione dato non esclude la possibilità di differenze run-to-run, a condizione che documenti esattamente quando si verifica ogni caso e esattamente cosa succede per ognuno. –

+1

@sharptooth: ho modificato la mia risposta, ma sono quasi certo che la risposta alla tua prima domanda è NO. Ad esempio considerando 'sizeof (int)', è garantito (come l'implementazione ha documentato il comportamento) di rimanere fisso per una particolare implementazione. .... Sono un po 'confuso da 'e implementare il comportamento in base a tale affermazione?' –

0

rand(3) in <stdlib.h> può essere chiamato da C++, non è sicuro di quanta parte della libreria C è inclusa in "standard C++", ma sicuramente c'è qualche meccanismo conforme agli standard per generare numeri casuali.

time(3) in <time.h> restituisce l'ora corrente; stessa storia con C++ e chiamata nella libreria C.

+1

come è rilevante per la domanda? – Naveen

+0

Are 'rand()' o 'time()' etichettato come definito dall'implementazione? Posso solo supporre che lo siano, e in tal caso sarebbero davvero un controesempio. Bene, a meno che non si consideri l'ora corrente e/o lo stato RNG del sistema come parte dell'input. –

+0

@naveen, ho pensato che 'rand()' sia specificato nello standard ma i dettagli sono definiti dall'implementazione. Sto avendo problemi a verificare questa ipotesi. – sarnold

6

Ovviamente, se l'implementazione documenta esattamente quando il comportamento cambia con esecuzioni diverse, va bene. Si noti che il comportamento definito dall'implementazione fa parte dei parametri della macchina astratta:

Le descrizioni semantiche nella presente norma internazionale definisce un parametrizzato non deterministico astratto macchina.

Alcuni aspetti e operazioni della macchina astratta sono descritti in questo standard internazionale come definito dall'implementazione (ad esempio, sizeof (int)). Questi costituiscono i parametri della macchina astratta. Ogni implementazione deve includere la documentazione che descrive le sue caratteristiche e il comportamento in questi aspetti. Tale documentazione deve definire l'istanza della macchina astratta che corrisponde a tale implementazione (indicata di seguito come '' istanza corrispondente '').

Ciò non consente di modificare il comportamento in una singola esecuzione del compilatore.Tuttavia, tra diverse esecuzioni del compilatore, il compilatore può utilizzare una macchina astratta corrispondente diversa che differisce in base a diversi valori definiti dall'implementazione, secondo quanto definito dall'implementazione. I parametri della riga di comando come -Wall (che modifica il set di messaggi diagnostici definito dall'implementazione) sono l'esempio più comune di questo. Questa è una differenza rispetto a comportamenti non specificati oltre ai requisiti della documentazione. Il comportamento non specificato è molto meno restrittivo:

Alcuni altri aspetti e operazioni della macchina astratta sono descritti in questo standard internazionale come non specificato (ad esempio, l'ordine di valutazione di argomenti per una funzione). Ove possibile, questo standard internazionale definisce un insieme di comportamenti consentiti. Questi definiscono gli aspetti non deterministici della macchina astratta. Un'istanza della macchina astratta può quindi avere più di una possibile sequenza di esecuzione per un dato programma e un dato input.

+0

'... definisce una macchina astratta non parametrica parametrizzata. 'Come la macchina astratta non è deterministica come è necessario che un comportamento sia coerente in una singola esecuzione del compilatore? –

+0

@Prasoon, solo alcuni percorsi, quelli in cui il comportamento non è specificato, introducono il non-determinismo. Ad esempio, l'espressione regolare 'z (a | b)' può essere espressa da una macchina a stati finiti non deterministici (NFA) che corrisponde a 'a' o' b' alla fine dell'input. Tuttavia, corrisponde costantemente a 'z' all'inizio dell'input :) Ora per il comportamento definito dall'implementazione, se i parametri (ad esempio,' z' all'inizio) cambiano, si otterrebbe una macchina astratta corrispondente diversa risultante. Non avresti più una singola implementazione tradurre il codice sorgente, ma due. :) –

+0

Ah !! E la domanda di sharptooth menziona che i dati di input sono richiesti "lo stesso" .... Phew! grazie Johannes :) –

1

IIRC, system() è necessario per esistere, ma dato il comportamento definito di implementazione. Qualcosa di simile sistema ("ls | grep foo"), naturalmente, avere effetti diversi a seconda che o meno il sistema in grado di eseguire qualcosa chiamato ls, che può variare tra le esecuzioni. E, anche su un abbastanza normale macchina UNIX in cui ls e grep fare ciò che ci si aspetta e non siano prese fuori, il risultato sarà comunque dipenderà dall'esistenza di un file con foo nel nome, che sarà sicuramente permesso di variare nel tempo e da dove viene eseguito il programma, ecc. Dipende solo da dove si disegna la linea di "gli stessi dati di input". Se la macchina si trova in uno stato perfettamente identico, allora ci si può aspettare un comportamento identico, ma non ci sono due esecuzioni che coinvolgeranno una macchina veramente in uno stato pedanticamente identico. (Anche la temperatura della CPU in macchine altrimenti perfettamente identiche potrebbe causare un comportamento di strozzatura, che altera il vincitore di alcune condizioni di gara, che visibilmente si traduce in un comportamento diverso del tuo programma.)

3

Un esempio che posso pensare di se il programma utilizza una rappresentazione big o little endian per i numeri. Credo che questo sarebbe sicuramente contare come un comportamento implementazione definita.

Su alcuni chip, ad esempio alcuni chip ARM, è possibile cambiare modalità in fase di esecuzione in modo che si desideri un compilatore che potrebbe produrre un programma che possa essere eseguito in entrambe le modalità, ovvero che si disponga di un comportamento definito dall'implementazione che potrebbe essere potenzialmente diverso su ogni corsa in base alle impostazioni esterne.

Allo stesso modo penso che si potrebbe scrivere un compilatore che ha prodotto sia a 32 bit ad 64 compilato dello stesso programma - e la modalità è eseguito è stato possibile determinare in fase di esecuzione. Ancora una volta, la documentazione dovrebbe dire che gli int sono stati a 32 bit o 64 bit a seconda di come lo hai eseguito.

A dire il vero non riesco a vedere nessuno fare nessuna di queste cose, ma entrambi sembrano esempi vagamente plausibili di quello che stavi chiedendo e non riesco a capire perché non sarebbero legali secondo lo standard finchè poiché la documentazione ha documentato correttamente la natura del comportamento dipendente dal sistema.

+0

+1, nei binari universali MacOSX contengono sia una versione a 32 che a 64 bit (nelle ultime versioni di MacOS X con supporto a 64 bit) e puoi scegliere al momento del lancio quale versione vuoi eseguire. I binari possono anche contenere codice per un'architettura completamente diversa come PowerPC. E nel caso ti chiedi, è utile.Ci sono alcuni plugin di safari che non funzionano a 64 bit, quindi puoi iniziare una sessione di safari a 32 bit quando ne hai bisogno. –

+0

Ah bene, non ero a conoscenza del fatto che MaxOSX ha fatto questo :) – jcoder

1

Le garanzie sono ciò che il compilatore ha documentato. Diverse flag di compilazione o di diverso stato del computer al momento della compilazione potrebbero influenzare il modo il compilatore/ottimizzatore elabora il programma e che possono avere un effetto sul risultato. Con bandiere compilatore avente il maggiore impatto (lo stesso compilatore può essere utilizzato per generare 32 e 64bit programmi in un ambiente a 64 bit, nelle due corse requisiti di allineamento possono differire).

Ci si può aspettare che nella maggior parte dei casi implementor fornirà alcune garanzie di base circa il comportamento della realizzazione e il programma genera per un dato insieme di parametri del compilatore/linker. Anche se il carico del sistema può influenzare quanto l'ottimizzatore può lavorare sul vostro programma --Alcune ottimizzatori saranno assegnati alcuni tempo-- limitata che non dovrebbe modificare il comportamento previsto.

Nota che, anche se non vi è alcuna garanzia, sarebbe difficile commercializzare un compilatore che produca codice con comportamenti diversi a seconda di parametri non correlati come la posizione della luna rispetto alle stelle.

Problemi correlati