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?
risposta
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.
"In C, gli argomenti delle funzioni vengono entrambi inseriti e estratti dalla pila dalla funzione chiamante." - Questo dipende dall'implementazione. –
@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) –
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. –
È 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.
Breve e dolce. +1 – cnicutar
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.
"Verso l'alto" nel diagramma, ma "verso il basso" in termini numerici. –
Oli, la pila può crescere in qualsiasi direzione. – Vovanium
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
- 1. Come vengono implementati gli argomenti variabili in gcc?
- 2. Come vengono implementati gli elenchi collegati senza l'uso del puntatore?
- 3. Come gestire gli argomenti di lunghezza variabile java in clojure?
- 4. Come vengono implementati gli array in Perl?
- 5. argomenti di lunghezza variabile C#
- 6. Come vengono implementati i tipi di membri?
- 7. Come vengono implementati gli automatismi finiti nel codice?
- 8. Come vengono implementati i riferimenti nella JVM di Oracle?
- 9. Elenco degli argomenti del modello di lunghezza variabile?
- 10. Elenco argomenti lunghezza variabile con argomento predefinito?
- 11. Come si converte da _TCHAR * a char * quando si usano gli argomenti di lunghezza variabile C++?
- 12. Array di lunghezza variabile
- 13. Come vengono implementati i test di chat di Facebook?
- 14. Come vengono implementati sbrk/brk in Linux?
- 15. Come vengono implementati malloc e gratuiti?
- 16. Come vengono implementati i riferimenti deboli?
- 17. Come vengono implementati i C# Generics?
- 18. Come vengono implementati i canali Go?
- 19. Come vengono implementati i parser DOM?
- 20. Come vengono implementati i blocchi try/catch?
- 21. Elenchi di lunghezza fissa e letterali tipo
- 22. PHPDoc per array di argomenti a lunghezza variabile
- 23. Elenchi di argomenti variabili in C++/CLI
- 24. sottostringa di lunghezza variabile
- 25. #define e funzioni con argomenti a lunghezza variabile
- 26. Come vengono risolti/dedotti gli argomenti dei template?
- 27. Gli array di lunghezza variabile sono possibili con Javascript
- 28. Come vengono passati gli argomenti delle funzioni in C?
- 29. Pygame ritarda quando vengono implementati due giocatori
- 30. Lunghezza variabile dell'elenco degli argomenti delle funzioni in Erlang
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. –
http://www.tenouk.com/Bufferoverflowc/Bufferoverflow3.html fare riferimento a questo sito –