Perché Objective-C memorizza oggetti nell'heap anziché nello stack?

3

Ho una conoscenza di base di cosa sono "stack" e "heap". Si utilizza una pila per memorizzare gli elementi in memoria che dovrebbero essere letti e / o rimossi in un modo ultimo letto / rimosso. Per rubare un altro esempio dal sito Web di qualcun altro, lo si utilizza per eseguire operazioni aritmetiche che coinvolgono PEMDAS. Si utilizza anche una pila per memorizzare gli indirizzi di ritorno per le funzioni. Come un heap, la CPU utilizza un puntatore per trovare l'elemento da leggere e / o rimuovere.

Usi un heap quando non hai bisogno del computer per memorizzare gli oggetti in ordine sequenziale in memoria.

La mia domanda è, qual è il problema con il puntatore * in Objective-C? Le variabili locali in un metodo stanno per essere deallocate quando il metodo è fatto comunque, quindi perché non usare lo stack invece?

Sto per uscire su un arto qui e dire che la risposta breve è che, poiché gli stack hanno una memoria limitata, Objective-C vuole mantenere l'utilizzo dello stack al minimo.

    
posta moonman239 31.07.2015 - 21:54
fonte

3 risposte

4

La ragione principale è che solo perché hai finito con un riferimento locale a un oggetto non significa che hai finito con l'oggetto stesso.

Ad esempio, se la funzione crea un oggetto e lo aggiunge a una raccolta preesistente che appartiene a un ambito più ampio, l'oggetto deve trovarsi nell'heap; qualsiasi cosa nello stack viene spostata dopo che la funzione è tornata, ma la raccolta (e tutti gli oggetti che contiene) è ancora valida.

Questo è solo uno dei tanti scenari in cui è necessario conservare un oggetto dopo che la funzione che lo ha creato per la prima volta restituisce. (Considerare anche il caso di una funzione il cui valore di ritorno è un oggetto appena creato, ad esempio ...) In tutti questi casi, è necessario mantenere il valore in una porzione di memoria non effimera.

Alcuni compilatori possono eseguire un trucco speciale noto come escape analysis , dove analizzano la vita dell'oggetto e se possono provare che l'oggetto non sopravviverà alla sua funzione, riscrivono il codice che lo crea per posizionalo in pila, rendendo la creazione e la pulizia più economica. Ma questa è un'analisi piuttosto avanzata (e molto difficile); è molto più semplice avere tutti gli oggetti allocati nello heap per impostazione predefinita.

    
risposta data 31.07.2015 - 22:02
fonte
2

Per entrare in un po 'di storia, non è sempre stato il caso che oggetti in pila fossero proibiti in Objective-C. Michael Rutman mi ha detto (nel 2009) che ciò avvenne in NeXTSTEP versione 2.0 nel 1990.

"Questa era la versione in cui sono state introdotte le zone, la nuova è stata sostituita con alloc / init e non sono più consentiti oggetti basati su stack."

Vedo dalla mia copia di "Programmazione orientata agli oggetti" di Brad Cox, datata 1987, che alloc e init non esistono e nuovo viene utilizzato per allocare gli array.

Sono state introdotte le zone per consentire al programmatore di specificare quale regione di memoria doveva essere utilizzata per l'oggetto; questo implicherebbe (anche se per certo avrei dovuto disturbare Michael Rutman o Brad Cox) che la ragione per cui non erano più semplicemente messi in pila era permettere (o forzare) al programmatore di pensare a dove stavano mettendo il loro oggetti.

alloc ha avuto una funzione sorella, allocWithZone. alloc usa una zona predefinita, mentre allocWithZone consente al programmatore di specificare la zona da utilizzare per questo oggetto. Memoria più veloce per alcuni, memoria più lenta per gli altri, raggruppare le cose in base alle esigenze.

Il manuale di GNU Step, link , nella sezione 3.1.2, discute e afferma che era per motivi di prestazioni.

Quindi, anche se oggi il motivo potrebbe essere che le persone discutono in altre risposte, ciò suggerirebbe che in origine si trattava di fornire ai programmatori il controllo per motivi di prestazioni. Ad esempio, consentiva ai programmatori di raggruppare insieme oggetti che sarebbero stati usati insieme di frequente, per ridurre il paging e simili.

    
risposta data 15.09.2015 - 21:10
fonte
1

In Objective-C, gli oggetti sono conteggiati. Un oggetto scompare quando non vi è più alcun riferimento ad esso. D'altra parte, gli oggetti in pila scompaiono quando termina la chiamata alla funzione. Riesci a vedere il problema? Se l'ultimo riferimento scompare prima della fine della chiamata, si spreca memoria. Se la chiamata alla funzione termina mentre ci sono ancora riferimenti all'oggetto, si ha un problema molto più serio.

Ora potrebbe avere oggetti sia nello stack che nell'heap, come fa il C ++. Ne vale la pena? C'è una maggiore complessità del codice e cosa guadagni realmente? L'allocazione della memoria nell'heap è veloce, dopotutto, se tutto è allocato sull'heap, hai una motivazione piuttosto strong per farlo in fretta.

    
risposta data 15.09.2015 - 21:54
fonte

Leggi altre domande sui tag