La ragione è semplice: gli argomenti della funzione vengono spinti nello stack dalla funzione chiamante (che è l'unica che può farlo perché solo ha le informazioni necessarie, dopo tutto il punto è farlo per passare quella informazione alla funzione chiamata). L'indirizzo di ritorno viene inviato allo stack dal meccanismo di chiamata della funzione. La funzione viene chiamata dopo la funzione chiamante è impostare i parametri, perché dopo la chiamata è chiamato funzione che viene eseguita, non chiamando uno.
OK, ora si potrebbe sostenere che la funzione chiamante potrebbe mettere i parametri al di là lo stack attualmente utilizzato, e la funzione chiamata potrebbe quindi basta regolare lo stack pointer di conseguenza. Ma non funzionerebbe bene perché in qualsiasi momento potrebbe esserci un interrupt o un segnale, che spingerebbe lo stato corrente sullo stack per ripristinarlo in un secondo momento (non sarei sorpreso se anche un interruttore di attività lo facesse) . Ma se si impostano i parametri oltre lo stack corrente, quegli eventi asincroni lo sovrascriveranno e, poiché non è possibile prevedere quando accadrà, non è possibile evitarlo (oltre la disabilitazione, che potrebbe avere altri svantaggi o addirittura essere impossibile, nel caso del commutatore di attività). In sostanza, tutto ciò che va oltre lo stack corrente deve essere considerato volatile.
noti inoltre che questo è indipendente dalla questione di chi pulisce i parametri. In linea di principio, la funzione chiamata potrebbe chiamare distruttori chiamate degli argomenti anche se fisicamente si trovano in stack frame del chiamante.Inoltre, molti processori (incluso x86) hanno istruzioni che fanno automaticamente spazio extra sopra l'indirizzo di ritorno al momento del ritorno (ad esempio, i compilatori Pascal lo facevano di solito perché in Pascal non si ha alcuna ripulitura oltre a restituire memoria, e almeno fr processori del tempo, era più efficiente pulire con quella istruzione del processore (non ho idea se ciò sia ancora vero per i processori moderni). C tuttavia non ha usato quel meccanismo a causa degli elenchi di argomenti di lunghezza variabile: per quelli, il meccanismo non era applicabile perché avresti bisogno di sapere in fase di compilazione quanto spazio extra da rilasciare, e K & RC non ha richiesto di inoltrare funzioni variadiche (C89 lo fa, ma pochi se qualsiasi compilatore ne approfitta, a causa della compatibilità con il vecchio codice), quindi non c'era modo per la funzione chiamante di sapere se pulire gli argomenti a meno che non lo facesse sempre.
Si prega di sapere che questa disposizione è ** non ** parte dello standard C++. È specifico per una singola CPU, un compilatore e/o un ambiente operativo. La situazione descritta in quell'articolo è tipica ed è accurata per GCC/X86, ma non è affatto universale. –
Il numero di entrambi i parametri e i locals potrebbe non essere corretto. Come hai potuto determinare l'indirizzo di tutti e 3 se l'indirizzo di ritorno non era nel mezzo? – Pubby
@Pubby: Non ho la risposta, ma questa situazione si verifica anche con ** Locals di DrawSquare ** e ** Parametri di DrawLine ** qui. – Lazer