2012-02-12 15 views
7

Da http://www.learncpp.com/cpp-tutorial/79-the-stack-and-the-heap/Come si accede alle variabili locali della funzione dallo stack?

Qui è la sequenza di passi che avviene quando una funzione è chiamato :

  1. L'indirizzo dell'istruzione oltre la chiamata di funzione viene inserito nello stack. In questo modo la CPU memorizza dove andare dopo la funzione restituisce.
  2. La sala viene creata in pila per il tipo di ritorno della funzione. Questo è solo un segnaposto per ora.
  3. La CPU salta al codice della funzione.
  4. L'attuale cima della pila viene tenuta in un puntatore speciale chiamato frame dello stack.
  5. Tutto aggiunto alla pila dopo che questo punto è considerato "locale" per la funzione.
  6. Tutti gli argomenti della funzione vengono posizionati nello stack.
  7. Le istruzioni all'interno della funzione iniziano l'esecuzione.
  8. Le variabili locali vengono inserite nello stack mentre vengono definite.

Non sono sicuro di come funziona il punto n. Se tutti gli argomenti della funzione sono messi in pila, come vengono acceduti?

Se, per esempio, ci sono tre argomenti a, b e c e sono posizionati sulla pila come questo da cima

| a | 
| b | 
| c | 
| | 
... 
|___| 

Ora, cosa succede quando la funzione vuole accedere c? Sono spuntati a e b?

+1

mi sembra impossibile che il passaggio 3 avvenga prima delle 6: ci dovrebbe essere * dentro * il codice della funzione corpo relativo alla valutazione del chiamante. Senza senso! – CapelliC

risposta

1

No, non lo sono. Il puntatore dello stack (in genere il registro esp) punta a a, esp+8h punti a b, esp+16h punti a c e così via. Non è necessario inserire a.

Si noti che questo è un dettaglio di implementazione. Non dovresti preoccuparti di questi. Il numero che ho dato è puramente teorico, su alcune architetture gli indirizzi discendenti sono dati a questi ultimi parametri, gli altri al contrario. Non è garantito che ciò accada.

MODIFICA: Mi sembra che non sia una fonte di informazioni molto affidabile. Parla di stack e heap, ma questi sono dettagli di implementazione e potrebbero anche non esserci.

Non c'è alcun vincolo nello standard per qualsiasi cosa da implementare tramite uno stack. Ad esempio, ho il seguente codice generato:

void foo(int x, int y, int z) 
{ 
01241380 push  ebp 
01241381 mov   ebp,esp 
01241383 sub   esp,0CCh 
01241389 push  ebx 
0124138A push  esi 
0124138B push  edi 
0124138C lea   edi,[ebp-0CCh] 
01241392 mov   ecx,33h 
01241397 mov   eax,0CCCCCCCCh 
0124139C rep stos dword ptr es:[edi] 
    int c = x; 
0124139E mov   eax,dword ptr [x] 
012413A1 mov   dword ptr [c],eax 
    c = y; 
012413A4 mov   eax,dword ptr [y] 
012413A7 mov   dword ptr [c],eax 
    c = z; 
012413AA mov   eax,dword ptr [z] 
012413AD mov   dword ptr [c],eax 
} 
012413B0 pop   edi 
012413B1 pop   esi 
012413B2 pop   ebx 
012413B3 mov   esp,ebp 
012413B5 pop   ebp 

Quindi, vedi, non c'è pila lì. Il runtime ha accesso diretto agli elementi: dword ptr [x], ecc.

+0

Ma generalmente uno stack è implementato in un modo in cui non è possibile accedere ad un elemento in altro modo rispetto all'implementazione di 'top()' .. cosa mi manca? – Lazer

+1

@Lazer: No. Stack è una struttura dati in cui è possibile aggiungere e rimuovere elementi dalla cima dello stack in tempo costante. Nessuno ha detto che non puoi accedervi casualmente. – ybungalobill

0

Utilizza il puntatore dello stack e un indirizzo relativo per indicare c.

11

Lo stack è uno stack metaforico . Ricorda è ancora una RAM, quindi puoi accedere a ciascun indirizzo senza saltare il resto, se sai cosa stai cercando.

Poiché la dimensione della variabile automatica è noto al momento della compilazione - i marchi compilatore offset per ciascuna variabile, il è determinata da dove la sezione variabili automatiche sulla pila start [o testa della pila di offset, entrambi sono validi e lo specifico l'implementazione dipende potrebbe dipendere dall'architettura], e accedervi semplicemente: start + offset per l'offset di ogni variabile.

+0

Su ogni piattaforma che è probabile incontrare, è uno stack metaforico. Se si trattasse di un vero stack che aveva solo operazioni push e pop, allora la funzione avrebbe dovuto escludere i parametri se ne avesse avuto bisogno "fuori servizio". –

+0

dove in memoria sono memorizzati gli offset? –

+0

@CaisManai L'offset è noto al momento della compilazione e non è necessario memorizzarlo. – amit

Problemi correlati