Domanda

Stavo leggendo su SIOF da un libro e ha dato un esempio:

//file1.cpp
extern int y;
int x=y+1;

//file2.cpp
extern int x;
int y=x+1;  

Ora la mia domanda è:
Nel codice di cui sopra, accadrà seguenti cose?

  1. durante la compilazione file1.cpp, foglie compilatore y come è cioè non assegnare memoria per esso.
  2. compilatore alloca memoria per x, ma non inizializzarlo.
  3. Durante la compilazione file2.cpp, foglie compilatore x come è cioè non alloca memoria per esso.
  4. compilatore alloca memoria per y, ma non inizializzarlo.
  5. durante il collegamento file1.o e file2.o, che ora ognuno file2.o è inizializzato prima, così ora:
    Fa x ottiene il valore iniziale di 0? o non ottiene inizializzato?
È stato utile?

Soluzione

Le fasi di inizializzazione sono riportati in 3.6.2 "Inizializzazione di oggetti non locali" della C ++ norma:

Fase 1: x e y sono inizializzati a zero prima di qualsiasi altra inizializzazione avviene.

Passaggio 2: x o y è dinamicamente inizializzata - che uno è specificata dallo standard. Quella variabile sarà ottenere il 1 value in quanto l'altra variabile sarà stato inizializzato a zero.

Passo 3:. L'altra variabile verrà inizializzato in modo dinamico, ottenendo il valore di 2

Altri suggerimenti

SIOF è molto un artefatto di runtime, il compilatore e il linker non hanno molto a che fare con esso. Si consideri la funzione atexit (), registra le funzioni che possono essere richiesti all'uscita dal programma. Molte implementazioni CRT hanno qualcosa di simile per l'inizializzazione del programma, chiamiamolo atinit ().

L'inizializzazione queste variabili globali richiede l'esecuzione di codice, il valore non può essere determinato dal compilatore. Quindi il compilatore genera frammenti di codice macchina che eseguono l'espressione e assegna il valore. Questi frammenti devono essere eseguite prima del main () viene eseguito.

Ecco dove atinit () entra in gioco. Un'implementazione comune CRT cammina un elenco di atinit puntatori a funzione ed eseguire i frammenti di inizializzazione, in ordine. Il problema è l'ordine in cui sono registrate le funzioni nella lista atinit (). Mentre atexit () ha un ordine LIFO ben definito, ed è implicitamente determinato dall'ordine in cui il codice chiama atexit (), tale non è il caso per le funzioni atinit. La specifica del linguaggio non richiede un ordine, non c'è nulla che si possa fare nel codice per specificare un ordine. SIOF è il risultato.

Una possibile implementazione è il compilatore che emette puntatori a funzione in una sezione separata. Il linker li unisce, producendo la lista atinit. Se il compilatore fa che poi l'ordine di inizializzazione sarà determinato dall'ordine in cui si collegano i file oggetto. Guardate il file di mappa, si dovrebbe vedere la sezione atinit se il compilatore fa questo. Non si chiamerà atinit, ma una sorta di nome, con "init" è probabile. Dando uno sguardo al codice sorgente CRT che chiama main () dovrebbe dare qualche idea pure.

Il punto (e il motivo si chiama un "fiasco") è che è impossibile dire con certezza cosa accadrà in un caso come questo. In sostanza, si sta chiedendo qualcosa di impossibile (che due variabili ogni essere più grande rispetto agli altri). Dal momento che non possono farlo, quello che faranno è aperto a qualche domanda - potrebbero produrre 0/1 o 1/0, o 1/2 o 2/1, o forse (migliore dei casi) solo un errore messaggio.

E 'compilatore dipendente e può essere runtime dipendente. Un compilatore può decidere di variabili pigramente inizializzazione statici quando si accede alla prima variabile in un file, o come si accede ogni variabile. Altrimenti sarà inizializzare tutte le variabili statiche per file al momento del lancio, con l'ordine di solito a seconda dell'ordine link del file. L'ordine di file potrebbe variare in base alle dipendenze o altri, compilatore influenze dipendenti.

Le variabili statiche sono di solito inizializzata a zero meno che non abbiano una costante inizializzatore. Di nuovo, questo è compilatore dipendente. Quindi, una di queste variabili sarà probabilmente pari a zero quando l'altro è inizializzato. Tuttavia, dal momento che entrambi hanno inizializzatori alcuni compilatori potrebbero lasciare i valori undefined.

Credo che lo scenario più probabile potrebbe essere:

  1. Lo spazio è assegnato per le variabili, ed entrambi hanno il valore 0.
  2. Una variabile, diciamo x, viene inizializzato e impostato sul valore 1.
  3. L'altro, detto y, viene inizializzato e impostato sul valore 2.

Si può sempre correre e vedere. Potrebbe essere che alcuni compilatori potrebbero generare il codice che va in un ciclo infinito.

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