Perché i libri dicono "il compilatore alloca lo spazio per le variabili in memoria"?

18

Perché i libri dicono, "il compilatore alloca lo spazio per le variabili in memoria". Non è l'eseguibile che lo fa? Voglio dire, ad esempio, se scrivo il seguente programma,

#include <iostream>
using namespace std;

int main()
{
   int foo;
   return 0;
}

e compilarlo, e ottenere un eseguibile (lascia che sia program.exe), ora, se eseguo program.exe, questo file eseguibile eseguirà esso stesso il comando per allocare un po 'di spazio per la variabile foo. Non è vero? Per favore, spiega perché i libri continuano a dire "il compilatore lo farà ... fallo".

    
posta The Peaceful Coder 04.04.2013 - 10:18
fonte

8 risposte

20

Hai ragione che il compilatore in quanto tale è scomparso quando il tuo programma viene effettivamente eseguito. E se gira su una macchina diversa, il compilatore non è nemmeno più disponibile.

Immagino che questo sia per fare una chiara distinzione tra la memoria effettivamente allocata dal tuo codice. Il compilatore inserirà del codice nel tuo programma che esegue l'allocazione della memoria (come l'uso di nuovi comandi, malloc o simili).

Quindi i libri usano "il compilatore fa questo o quello" spesso per dire che il compilatore ha aggiunto del codice che non è esplicitamente menzionato nei file di codice. Abbastanza vero che questo non è esattamente quello che sta succedendo. Da questo punto di vista molte cose menzionate nei tutorial sarebbero sbagliate, ma avrebbero bisogno di spiegazioni piuttosto elaborate.

    
risposta data 04.04.2013 - 10:25
fonte
4

Dipende dalla variabile. Il sistema operativo alloca l'heap, il programma alloca lo stack e il compilatore alloca lo spazio per globals / statics, cioè sono integrati nell'exe stesso. Se assegni 1MB di memoria globale, la dimensione del tuo exe aumenterà di almeno 1MB

    
risposta data 04.04.2013 - 17:18
fonte
4

ciò che il compilatore farà farà è prendere il tuo codice e compilarlo in codice macchina. Quello che citi è un buon esempio in cui un compilatore deve solo tradurre.

Ad esempio, quando scrivi

int foo;

Puoi vedere che come 'sto dicendo al compilatore di [ nell'output che genera ] richiesta che il computer riservi abbastanza ram per un int a cui posso fare riferimento più avanti. Il compilatore probabilmente userà un ID risorsa o qualche meccanismo per rintracciare foo nel codice macchina, puoi usare foo in un file di testo invece di scrivere assembly! Evviva

Quindi potresti anche considerare questo come il compilatore sta scrivendo una lettera ( o forse un romanzo / enciclopedia ) a tutti i processori e dispositivi mirati. La lettera è scritta in segnali binari che (generalmente) possono essere tradotti in processori diversi cambiando l'obiettivo. Qualsiasi 'lettera' e / o combo può inviare qualsiasi tipo di richiesta e / o dati - ad esempio, si prega di allocare lo spazio per questa variabile che il programmatore ha usato.

    
risposta data 04.04.2013 - 10:58
fonte
3

Dire che "il compilatore alloca la memoria" potrebbe non essere effettivamente accurato in senso letterale, ma è una metafora che è suggestiva nel modo giusto.

Ciò che realmente accade è che il compilatore crea un programma che alloca la propria memoria. Tranne che non è il programma che alloca la memoria, ma il sistema operativo.

Quindi ciò che realmente accade è che il compilatore crea un programma che descrive i suoi requisiti di memoria e il sistema operativo prende quella descrizione e la usa per allocare memoria. Tranne che il sistema operativo è un programma, e i programmi in realtà non fanno nulla, descrivono un calcolo che viene eseguito dalla CPU. Tranne che la CPU è in realtà solo un complicato circuito elettronico, non un piccolo omologo antropomorfizzato.

Ma ha senso pensare a programmi, compilatori e CPU come piccole persone che vivono all'interno di un computer, non perché lo siano effettivamente, ma perché è una metafora che si adatta bene al cervello umano.

Alcune metafore funzionano bene per descrivere le cose a un livello di astrazione, ma non funzionano altrettanto bene ad un altro livello. Se si pensa al livello del compilatore, ha senso descrivere l'atto di generare codice che determinerà l'allocazione della memoria quando il programma che viene compilato viene effettivamente eseguito come "allocazione della memoria". È abbastanza vicino che, quando stiamo pensando a come funziona un compilatore, abbiamo l'idea giusta, e non è così prolisso che dimentichiamo quello che stavamo facendo. Se proviamo a usare quella metafora a livello del programma compilato in esecuzione, è fuorviante in un modo strano, che è ciò che hai notato.

    
risposta data 02.10.2013 - 17:16
fonte
0

È il compilatore che decide dove memorizzare una variabile - può essere nello stack o in un registro gratuito. Qualunque sia la decisione di archiviazione presa dal compilatore, il codice macchina corrispondente per accedere a quella variabile verrà generato e non può essere modificato in fase di esecuzione. In questo senso, il compilatore ha il compito di allocare spazio per le variabili e il programma finale.exe si comporta in modo cieco come uno zombie in fase di esecuzione.

Ora, non confondere questo con una gestione dinamica della memoria diversa come malloc, nuova o potrebbe essere la tua gestione della memoria. I compilatori hanno a che fare con l'archiviazione e l'accesso alle variabili, ma non importa cosa significhi un valore reale in un altro framework / libreria. Ad esempio:

byte* pointer = (byte*)malloc(...);

In fase di esecuzione, malloc può restituire un numero arbitrario, ma al compilatore non interessa, tutto ciò che importa è dove memorizzare quel numero.

    
risposta data 03.10.2013 - 00:05
fonte
0

Un fraseggio più accurato sarebbe: - "il compilatore dice al loader di riservare spazio per le variabili"

In un ambiente C-ish ci saranno tre tipi di spazio per le variabili: -

  • un blocco fisso per variabili statiche
  • Un grande blocco per variabili "automatiche" di solito denominato "stack". Le funzioni catturano un blocco alla voce e lo rilasciano al ritorno.
  • Un grande blocco chiamato "heap", da cui viene allocata la memoria gestita dal programma (usando malloc () o un'API di gestione della memoria simile.

In una moderna memoria heap del sistema operativo in realtà non verrà riservata, ma allocata come richiesto.

    
risposta data 03.10.2013 - 09:25
fonte
0

Sì, hai ragione, in questo caso (dichiarando una variabile in una funzione), la frase del tuo libro è probabilmente errata: quando dichiari una variabile in una funzione, essa viene allocata nello stack quando si entra nella funzione . Ad ogni modo, un compilatore dovrebbe ottimizzare la situazione: se la funzione non è ricorsiva ( main() è un buon candidato per questo), va bene "allocare" il tempo di compilazione (sul BSS).

(Se sei curioso di sapere dove si trovano le tue variabili, puoi controllarlo in modo sporco (se non vuoi esaminare la struttura del file obj, comunque, perché no?), quindi puoi dichiarare alcune differenze tipo di variabili: costante, statico, dinamico, malloc() -allocato ecc. e visualizza i loro indirizzi (usa %X formattatore in printf() per una migliore leggibilità). Le variabili che si trovano nello stack avranno indirizzi di memoria molto diversi. )

    
risposta data 19.12.2013 - 09:40
fonte
0

L'unica cosa fatta in fase di esecuzione sarà il bumping dello stack poinbter di una certa quantità. Quindi il compilatore decide in anticipo:

  • quanto spazio di stack sarà necessario per la funzione.
  • A quale distanza dal puntatore dello stack verrà applicata ogni singola variabile essere localizzato.

Questo può essere chiamato "allocazione", ma ovviamente, durante il periodo di compilazione, si posiziona solo nel modello del compilatore che ha il programma in esecuzione.

    
risposta data 19.12.2013 - 10:52
fonte

Leggi altre domande sui tag