2011-12-26 19 views
5

Cosa succede internamente quando viene chiamata una funzione che utilizza vararg? Gli argomenti stessi sono archiviati nell'heap o nella pila come qualsiasi altro argomento. Se in pila, come funziona?Come vengono implementati gli elenchi di argomenti di lunghezza variabile?

+1

Risposta breve: dipende dall'implementazione. Di solito puoi avere un'idea di cosa sta succedendo leggendo le macro nei file include. stdarg.h è la forma "moderna" di questo, varargs.h ha la versione precedente, deprecata. Dal momento che hai detto specificatamente varargs, prova a leggere varargs.h. –

+0

http://www.tenouk.com/Bufferoverflowc/Bufferoverflow3.html fare riferimento a questo sito –

risposta

1

In C, gli argomenti delle funzioni vengono entrambi inseriti e estratti dallo stack dalla funzione del chiamante. La funzione del chiamante sa quanti oggetti sono stati inseriti e quindi è anche in grado di richiamarli dopo la chiamata. Il callee può solo inferire il numero degli argomenti da altri parametri, come la stringa di formato di printf().

In Pascal, ad esempio, gli argomenti nello stack vengono estratti dal destinatario. Dato che il destinatario non è a conoscenza del numero di elementi inviati, non può ripristinare lo stack al suo stato precedente. Ecco perché è impossibile implementare vararg in Pascal.

+0

"In C, gli argomenti delle funzioni vengono entrambi inseriti e estratti dalla pila dalla funzione chiamante." - Questo dipende dall'implementazione. –

+0

@OliCharlesworth Questo è vero. Ho pensato che C fosse configurato per usare la convenzione chiamata 'cdecl', che" è usata da molti sistemi C per l'architettura x86. "(Http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl) –

+1

Inoltre, vorrei immagina che Pascal * possa * avere vararg, se fosse intelligente a riguardo --- puoi fornire il numero di argomenti come primo argomento, ad esempio (e/o lo stack in alto). Dovresti stare attento all'attuazione, ovviamente, ma potrebbe essere fattibile. –

8

È dipendente dall'implementazione. Ma molto probabilmente, gli argomenti vengono posti in pila, uno dopo l'altro (dopo che sono state eseguite le promozioni degli argomenti predefiniti).

va_start, va_arg ecc. Funzionano semplicemente spostando un puntatore nella pila e reinterpretando i bit come qualsiasi tipo di richiesta.

+0

Breve e dolce. +1 – cnicutar

5

Come è stato notato prima, dipende dall'implementazione.

Nella convenzione di chiamata C (noto come cdecl), gli argomenti vengono inseriti nello stack in ordine inverso, in modo da:

void myfunc(int one, int two, int three) 

sarà simile a questa in pila dopo che si chiama (lo stack cresce verso l'alto, verso 0):

.    .    0x00000000 
    .    . 
    .    . 
    | current frame | 
    |----------------| 
    | return address | 
    |----------------|     ^
    | one   |     | stack 
    |----------------|     | growth 
    | two   |     | direction 
    |----------------|     | 
    | three  | 
    |----------------| 
    | previous frame | 
     ...  
     ...      0xFFFFFFFF 

Così, il primo argomento può essere recuperata prima (perché sappiamo che la sua posizione, è solo prima che l'indirizzo di ritorno), e spero che contiene abbastanza informazioni su come molti altri argomenti sono presenti. Ad esempio, in printf(3) e funzioni correlate, tutte le informazioni sugli altri argomenti sono presenti nella stringa di formato, che è il primo argomento.

+0

"Verso l'alto" nel diagramma, ma "verso il basso" in termini numerici. –

+0

Oli, la pila può crescere in qualsiasi direzione. – Vovanium

+0

Sì, lo scopo del commento "verso l'alto" era di dare allo stack una direzione. Personalmente, tuttavia, trovo più semplice pensare a una pila come a una specie di Torre di Hanoi. – cha0site

Problemi correlati